package com.yanqu.road.server.manager.activity.peakseacraft;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.CrossActivityDetail;
import com.yanqu.road.entity.activity.peakseacraft.*;
import com.yanqu.road.entity.activity.peakseacraft.config.PeakSeacraftActivityConfig;
import com.yanqu.road.entity.activity.seacraft.config.SeacraftSouthSeaShipConfig;

import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.log.LogPeakSeacraftDonation;
import com.yanqu.road.entity.log.LogPeakSeacraftGuess;
import com.yanqu.road.entity.log.LogPeakSeacraftTeam;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.union.UnionBaseInfo;
import com.yanqu.road.logic.bussiness.activity.PeakSeacraftBusiness;
import com.yanqu.road.logic.helper.UnionHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.pb.activity.PeakSeacraftProto;
import com.yanqu.road.pb.activity.SeacraftSouthSeaProto;
import com.yanqu.road.pb.activity.StrongholdWarProto;
import com.yanqu.road.pb.commonactivity.CommonActivityProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.pb.rank.UnionActivityRankProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.config.PatronsMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankCacheMgr;
import com.yanqu.road.server.manager.yrank.CrossYRankMgr;
import com.yanqu.road.server.manger.TempGoodsBagMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.util.ConcurrentHashSet;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description 巅峰海上争霸
 */
public class PeakSeacraftActivity {

    private static Logger logger = LogManager.getLogger(PeakSeacraftActivity.class.getName());
    private RandomHelper randomHelper = new RandomHelper();
    private int activityId;
    private int unionGroup;
    private PeakSeacraftActivityConfig config;

    /**
     * 组数据 k: 海域 v: k:group v:info
     */
    private Map<Integer, Map<Integer, PeakSeacraftGroupInfo>> areaGroupMap = new ConcurrentHashMap<>();

    /**
     * 参与的联盟信息
     */
    private Map<String, PeakSeacraftUnionInfo> unionInfoMap = new ConcurrentHashMap<>();

    /**
     * 玩家数据,这里只放争霸中的玩家
     */
    private Map<Long, PeakSeacraftCrossUserInfo> userInfoMap = new ConcurrentHashMap<>();

    /**
     * 玩家竞猜数据,这里放所有参与的玩家
     */
    private Map<Long, PeakSeacraftCrossUserGuessData> userGuessDataMap = new ConcurrentHashMap<>();

    /**
     * 总排行榜
     */
    private List<PeakSeacraftUnionInfo> rankList = new CopyOnWriteArrayList<>();

    /**
     * 竞猜数据 k:roundId, k:晋级联盟 v: 竞猜的数量
     */
    private Map<Integer, Map<String, Integer>> guessMap = new ConcurrentHashMap<>();

    /**
     * 竞猜数据 k:roundId 南海丝路轮次, k:猜中的档位 v:猜中的玩家集合
     */
    private Map<Integer, Map<Integer, List<Long>>> guessTimesMap = new ConcurrentHashMap<>();

    /**
     * 最新的跑马灯
     */
    public Map<Integer, PeakSeacraftProto.PeakSeacraftMarqueeInfo.Builder> lastMarqueeInfo = new ConcurrentHashMap<>();

    /**
     * 报名期 晋级的联盟数据是否 全部同步了
     */
    public AtomicBoolean isSyn = new AtomicBoolean(false);

    private int reqLockMsgServerIdIdx = 0;

    /**
     * 缓存的排行消息
     */
    private UnionActivityRankProto.UnionActivityRankListMsg.Builder rankListMsg = UnionActivityRankProto.UnionActivityRankListMsg.newBuilder();

    public PeakSeacraftActivity(PeakSeacraftActivityConfig config, int unionGroup) {
        this.config = config;
        this.activityId = config.getActivityInfo().getActivityId();
        this.unionGroup = unionGroup;
        // 加载数据
        initActivityInfo();
    }

    public PeakSeacraftActivityConfig getConfig() {
        return config;
    }

    public void updateConfig(PeakSeacraftActivityConfig config) {
        this.config = config;
        this.activityId = config.getActivityInfo().getActivityId();
    }

    public void initActivityInfo() {
        // 加载数据库数据
        loadData();
        // 晋级联盟
        unionInfoMap.values().forEach(e -> {
            rankList.add(e);
            PeakSeacraftGroupInfo groupInfo = getGroupInfo(e.getUnionData().getArea(), e.getUnionData().getGroupNum(), true);
            groupInfo.addUnionInfo(e);
        });
        sortUnionGroupRank();
        refreshUnionRank();
        if (!rankList.isEmpty()) {
            parseUnionRankMsg(rankList);
        }

        // 竞猜数据
        userGuessDataMap.values().forEach(e -> {
            for (Map.Entry<Integer, PeakSeacraftGuessInfo> entry : e.getGuessMap().entrySet()) {
                int round = entry.getKey();
                List<String> unionList = entry.getValue().getUnionList();
                Map<String, Integer> map = guessMap.get(round);
                if (map == null) {
                    map = new ConcurrentHashMap<>();
                    guessMap.put(round, map);
                }
                for (String unionId : unionList) {
                    int num = map.getOrDefault(unionId, 0);
                    map.put(unionId, num + 1);
                }
            }
        });
        if (config.getCurRound() > config.getMaxRoundCount()) {
            guessSuccess(false);
        }
    }

    private void loadData() {
        Map<String, PeakSeacraftCrossUnionData> unionDataMap = PeakSeacraftBusiness.getPeakSeacraftCrossUnionDataMap(activityId, unionGroup);
        unionDataMap.values().forEach(e -> {
            unionInfoMap.put(e.getUnionId(), new PeakSeacraftUnionInfo(e));
        });
        Map<String, PeakSeacraftCrossUnionShipData> shipDataMap = PeakSeacraftBusiness.getPeakSeacraftCrossUnionShipDataMap(activityId, unionGroup);
        shipDataMap.values().forEach(e -> {
            PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(e.getUnionId());
            if (unionInfo == null) {
                logger.error("海上争霸 南海丝路 有PeakSeacraftCrossUnionShipData数据 却没有 联盟数据 activityId:{},unionId:{}", e.getActivityId(), e.getUnionId());
            } else {
                unionInfo.setShipData(e);
            }
        });

        Map<Long, PeakSeacraftCrossUserData> userDataMap = PeakSeacraftBusiness.getPeakSeacraftCrossUserDataMap(activityId, unionGroup);
        userDataMap.values().forEach(e -> {
            PeakSeacraftCrossUserInfo userInfo = new PeakSeacraftCrossUserInfo(e);
            userInfoMap.put(e.getUserId(), userInfo);
            if (!StringUtils.isNullOrEmpty(e.getUnionId())) {
                PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(e.getUnionId());
                if (unionInfo == null) {
                    logger.info("海上争霸 南海丝路 有PeakSeacraftCrossUserData数据 却没有 联盟数据 activityId:{},unionId:{},userId:{}", e.getActivityId(), e.getUnionId(), e.getUserId());
                } else {
                    unionInfo.getMemberMap().put(e.getUserId(), userInfo);
                }
            }
        });
        Map<Long, PeakSeacraftCrossChallengeData> challengeMap = PeakSeacraftBusiness.getPeakSeacraftCrossChallengeDataMap(activityId, unionGroup);
        challengeMap.values().forEach(e -> {
            PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(e.getUserId());
            if (userInfo == null) {
                logger.info("海上争霸 南海丝路 有PeakSeacraftCrossChallengeData数据 却没有 玩家数据 activityId:{},userId:{}", e.getActivityId(), e.getUserId());
            } else {
                userInfo.setChallengeData(e);
            }
        });
        int curRound = getCurRound();
        long time = 0;
        if (curRound > 0) {
            time = PeakSeacraftMgr.getRoundStartTime(activityId, curRound);
        }
        List<PeakSeacraftBattleDetailData> battleDetailList = PeakSeacraftBusiness.getPeakSeacraftBattleDetailDataList(activityId, time, unionGroup);
        battleDetailList.forEach(e -> {
//            if (e.getRound() == 0) {
//                e.setRound(curRound);
//            }
            PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(e.getUnionId());
            if (unionInfo == null) {
                logger.error("海上争霸 南海丝路 有PeakSeacraftBattleDetailData数据 却没有 联盟数据 activityId:{},unionId:{}", e.getActivityId(), e.getUnionId());
            } else {
                if (e.getMasterType() == 0) {
                    unionInfo.getAttackBattleMap().put(e.getTargetUnionId(), e);
                } else if (e.getMasterType() == 1) {
                    unionInfo.getDefendBattleMap().put(e.getTargetUnionId(), e);
                }
            }
        });
        List<PeakSeacraftCrossRecordData> list = PeakSeacraftBusiness.getPeakSeacraftCrossRecordDataList(activityId, time, unionGroup);
        list.forEach(e -> {
            PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(e.getUnionId());
            if (unionInfo == null) {
                logger.error("海上争霸 南海丝路 有PeakSeacraftCrossRecordData数据 却没有 联盟数据 activityId:{},unionId:{}", e.getActivityId(), e.getUnionId());
            } else {
                unionInfo.addRecord(e, config.getSEACRAFT_CRAFT_SHIP_NUM());
            }
        });

        userGuessDataMap = PeakSeacraftBusiness.getPeakSeacraftCrossUserGuessDataMap(activityId, unionGroup);
    }

    public void save() {
        for (PeakSeacraftUnionInfo item : unionInfoMap.values()) {
            // union
            if (item.getUnionData().isUpdateOption()) {
                PeakSeacraftBusiness.updatePeakSeacraftCrossUnionData(item.getUnionData());
            } else if (item.getUnionData().isInsertOption()) {
                PeakSeacraftBusiness.addPeakSeacraftCrossUnionData(item.getUnionData());
            }
            // ship
            if (item.getShipData() != null) {
                if (item.getShipData().isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftCrossUnionShipData(item.getShipData());
                } else if (item.getShipData().isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftCrossUnionShipData(item.getShipData());
                }
            }
            for (PeakSeacraftBattleDetailData battleDetailData : item.getAttackBattleMap().values()) {
                if (battleDetailData.isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftBattleDetailData(battleDetailData);
                } else if (battleDetailData.isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftBattleDetailData(battleDetailData);
                }
            }

            for (PeakSeacraftBattleDetailData battleDetailData : item.getDefendBattleMap().values()) {
                if (battleDetailData.isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftBattleDetailData(battleDetailData);
                } else if (battleDetailData.isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftBattleDetailData(battleDetailData);
                }
            }

            // 攻击
            for (PeakSeacraftCrossRecordData recordData : item.getAttackRecordList()) {
                if (recordData.isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftCrossRecordData(recordData);
                } else if (recordData.isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftCrossRecordData(recordData);
                }
            }
            // 防守
            for (PeakSeacraftCrossRecordData recordData : item.getDefendRecordList()) {
                if (recordData.isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftCrossRecordData(recordData);
                } else if (recordData.isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftCrossRecordData(recordData);
                }
            }
        }
        for (PeakSeacraftCrossUserInfo item : userInfoMap.values()) {
            if (item.getBaseData().isUpdateOption()) {
                PeakSeacraftBusiness.updatePeakSeacraftCrossUserData(item.getBaseData());
            } else if (item.getBaseData().isInsertOption()) {
                PeakSeacraftBusiness.addPeakSeacraftCrossUserData(item.getBaseData());
            }
            // 挑战数据
            if (item.getChallengeData() != null) {
                if (item.getChallengeData().isUpdateOption()) {
                    PeakSeacraftBusiness.updatePeakSeacraftCrossChallengeData(item.getChallengeData());
                } else if (item.getChallengeData().isInsertOption()) {
                    PeakSeacraftBusiness.addPeakSeacraftCrossChallengeData(item.getChallengeData());
                }
            }
        }
        List<PeakSeacraftCrossUserGuessData> guessList = getGuessList();
        for (PeakSeacraftCrossUserGuessData userGuessData : guessList) {
            if (userGuessData.isUpdateOption()) {
                PeakSeacraftBusiness.updatePeakSeacraftCrossUserGuessData(userGuessData);
            } else if (userGuessData.isInsertOption()) {
                PeakSeacraftBusiness.addPeakSeacraftCrossUserGuessData(userGuessData);
            }
        }

    }

    /**
     * 刷新联盟排行榜
     */
    public void refreshUnionRank() {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return;
        }
        int activityCurRound = getActivityCurRound();
        if (getActivityCurRound() <= 0) {
            return;
        }
        refreshCurJoinUnionShip();
        long now = DateHelper.getCurrentTime();
        for (PeakSeacraftUnionInfo item : rankList) {
            item.distance = item.getDistance(this, activityCurRound, now);
        }
        unionRankSort();
    }

    /**
     * 检查是否要请求锁定报名期名单
     */
    public synchronized void checkRegistrationEnd() {
        if (!rankList.isEmpty()) {//已经有名单了
            return;
        }
        // 获取一些数据
        if (config.roundTimeList.isEmpty() || config.roundTimeList.get(0).length < 3) {
            return;
        }
        // 还没到
        // 额外多十秒等商会成员变化结束
        long fixTime = config.getActivityInfo().getBeginTime() + config.registrationEndTime + 30;
        if (fixTime > System.currentTimeMillis() / 1000) {
            return;
        }

        //找一个游戏服请求名单 这里后面优化一下，如果几秒内没返回名单就换一个游戏服请求
        for (int i = 0; i < config.getActivityInfo().getServerIdList().size(); i++) {
            int idx = i + 1;
            if (reqLockMsgServerIdIdx == 0) {
                reqLockMsgServerIdIdx = idx;
            } else if (idx > reqLockMsgServerIdIdx) {
                reqLockMsgServerIdIdx = idx;
            } else if (reqLockMsgServerIdIdx >= config.getActivityInfo().getServerIdList().size()) {
                reqLockMsgServerIdIdx = 1;
            } else {
                continue;
            }

            long serverId = config.getActivityInfo().getServerIdList().get(i);
            MessageHelper.sendPacket(serverId, 0,
                    YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_UNION_MAX_ABILITY_RANK_LOCK,
                            CommonActivityProto.CommonActivityRankListReqMsg.newBuilder().setGroupId(unionGroup).setActivityId(activityId)));
            break;
        }
    }

    /**
     * 锁定报名期名单
     *
     * @param lockMsg
     */
    public synchronized void lockRegistrationPromotionUnion(RankProto.CrossUnionRankListLockMsg lockMsg) {
        if (!rankList.isEmpty()) {
            //有名单了
            return;
        }
        List<PeakSeacraftUnionInfo> list = new ArrayList<>();
        int numLimit = config.getRegistrationNum();
        for (int i = 0; i < lockMsg.getRankList().size() && i < numLimit; i++) {
            RankProto.CrossUnionRankLockTemp rankTempMsg = lockMsg.getRank(i);
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(rankTempMsg.getRankTemp().getUnionUid(), true);
            unionInfo.getUnionData().setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(rankTempMsg.getRankTemp().getUnionBaseData()));
            unionInfo.getUnionData().setTotalAbility(new BigInteger(rankTempMsg.getRankTemp().getValue()));
            unionInfo.getUnionData().setAbilityRank(i + 1);

            for (RankProto.CrossUnionMemberTemp memberTemp : rankTempMsg.getMemberList()) {
                PeakSeacraftCrossUserInfo memberInfo = unionInfo.initMember(activityId, memberTemp.getMemberId(), memberTemp.getServerId());
                userInfoMap.put(memberInfo.getBaseData().getUserId(), memberInfo);
            }

            rankList.add(unionInfo);
        }
        //更新回合
        setActivityCurRound(1);

        rankList.addAll(list);

        devideIntoGroups(1, rankList);

        //更新组内排名
        sortUnionGroupRank();
        parseUnionRankMsg(unionRankSort());

        updateShipNumber();
    }

    /**
     * 更新总榜单
     */
    private List<PeakSeacraftUnionInfo> unionRankSort() {
        List<PeakSeacraftUnionInfo> list = new ArrayList<>();
        synchronized (rankList) {
            rankList.sort((t1, t2) -> {
                return unionRankCompare(t1, t2);
            });

            int rank = 1;
            for (PeakSeacraftUnionInfo unionInfo : rankList) {
                unionInfo.getUnionData().setRank(rank++);
                list.add(unionInfo);
            }
        }

        return list;
    }

    /**
     * 分组 分组规则参照统兵演武com.yanqu.road.server.manager.activity.tongbing.activity.CrossTongBingActivity#lockCamp(java.util.List)
     *
     * @param area       海域
     * @param unionDatas 按报名期赚钱排序好的列表
     */
    public synchronized void devideIntoGroups(int area, List<PeakSeacraftUnionInfo> unionDatas) {
        if (unionDatas.isEmpty()) {
            return;
        }

        int groupPerNum = config.getGroupPerNum();
        int groupNeed = (unionDatas.size() + groupPerNum - 1) / groupPerNum;
        int newGroupPerNum = BigDecimal.valueOf(unionDatas.size())
                .divide(BigDecimal.valueOf(groupNeed), 0, BigDecimal.ROUND_UP).intValue();

        Map<Integer, PeakSeacraftGroupInfo> groupMap = new ConcurrentHashMap<>();
        Map<Integer, BigInteger> groupAbilityMap = new ConcurrentHashMap<>();
        for (int i = 1; i <= groupNeed; i++) {
            PeakSeacraftGroupInfo groupInfo = getGroupInfo(area, i, true);
            groupMap.put(i, groupInfo);
            groupAbilityMap.put(i, BigInteger.ZERO);
        }

        for (int r = 0; r < unionDatas.size(); r++) {
            PeakSeacraftUnionInfo unionInfo = unionDatas.get(r);
            int minGruop = 1;
            BigInteger minAbility = BigInteger.ZERO;
            for (Map.Entry<Integer, BigInteger> entry : groupAbilityMap.entrySet()) {
                // 跳过已经分配满的阵营
                if (groupMap.get(entry.getKey()).getUnionAmount() >= newGroupPerNum) {
                    continue;
                }
                if (entry.getValue().equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    break;
                }
                if (minAbility.equals(BigInteger.ZERO)) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                    continue;
                }

                // 取总赚钱最小的阵营（赚钱相同时，随机一下，避免一直一样）
                if (entry.getValue().compareTo(minAbility) < 0 ||
                        entry.getValue().equals(minAbility) && randomHelper.next(2) == 0) {
                    minGruop = entry.getKey();
                    minAbility = entry.getValue();
                }
            }

            groupMap.get(minGruop).addUnionInfo(unionInfo);
            groupAbilityMap.put(minGruop, groupAbilityMap.get(minGruop).add(unionInfo.getUnionData().getTotalAbility()));

            // 修改数据
            unionInfo.getUnionData().setGroupNum(minGruop);
            unionInfo.getUnionData().setArea(area);
            unionInfo.getUnionData().setRound(getActivityCurRound());
        }

    }

    /**
     * 锁定晋级南海丝路 的名额 在这里分组
     */
    public synchronized void lockPromotionUnion(int round) {
        if (0 == round) {
            return;
        }
        if (round <= 1) {
            checkRegistrationEnd();
            return;
        }
        if (!isSyn.get()) {
            return;
        }

        int activityCurRound = getActivityCurRound();
        if (activityCurRound >= round) {
            return;
        }
        // 找到对应 的晋级名单
        int promotionNum = config.thisRoundNexAreaPromotionNum(round);
        // 新的海域对应联盟
        Map<Integer, List<PeakSeacraftUnionInfo>> areaUnionListMap = new ConcurrentHashMap<>();

        //积分结算前排总排名
        refreshUnionRank();

        areaGroupMap.forEach((area, groupPeakSeacraftGroupInfoMap) -> {
            groupPeakSeacraftGroupInfoMap.forEach((group, peakSeacraftGroupInfo) -> {
                synchronized (peakSeacraftGroupInfo) {
                    peakSeacraftGroupInfo.sortUnionList(this);
                    peakSeacraftGroupInfo.settleUnionMap(round - 1, promotionNum, config, areaUnionListMap);
                }
            });
        });

        //更新回合
        setActivityCurRound(round);

        //分组
        if (round <= config.getMaxRoundCount()) {//最后一轮不重新分组
            areaGroupMap.clear();//重置组数据
            areaUnionListMap.forEach((area, unionInfoList) -> {
                unionInfoList.sort((o1, o2) -> {
                    return o2.getUnionData().getTotalAbility().compareTo(o1.getUnionData().getTotalAbility());
                });

                //通知更新海域成就
                for (PeakSeacraftUnionInfo unionInfo : unionInfoList) {
                    if (unionInfo.getUnionData().getArea() == area) {//这里海域还没变更,所以相等的就是没晋级海域的
                        continue;
                    }
                    for (PeakSeacraftCrossUserInfo userInfo : unionInfo.getMemberMap().values()) {
                        long serverId = userInfo.getBaseData().getServerId();
                        long userId = userInfo.getBaseData().getUserId();
                        notifyUpdateUserCondition(serverId, userId, area);
                    }
                }

                devideIntoGroups(area, unionInfoList);
            });

            //最后一轮结算后不用再排名了
            //更新组内排名
            sortUnionGroupRank();
        }

        parseUnionRankMsg(unionRankSort());

        if (round > config.getMaxRoundCount()) {//第三轮结束的计算，进来的round==4
            guessSuccess(true);
        }

        updateShipNumber();
    }

    /**
     * 同步锁定联盟的联盟成员给跨服
     *
     * @param unionList
     */
    public void synPromotionUnion(List<PeakSeacraftProto.PeakSeacraftUnionInfo> unionList) {
        for (PeakSeacraftProto.PeakSeacraftUnionInfo item : unionList) {
            logger.info("巅峰海上争霸 收到来着区服的联盟数据 activityId:{},unionId:{},memberNum:{}", activityId, item.getUnionId(), item.getMemberInfoListList().size());
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(item.getUnionId(), true);
            unionInfo.getUnionData().setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(item.getUnionBaseInfo()));
            item.getMemberInfoListList().forEach(e -> {
                // 锁定小队
                initUserInfo(e.getUserId(), item.getUnionId(), e.getServerId(), e.getPosition());
                // 做个保护防止 联盟成员时变更没有同步
                joinUnion(e.getUserId(), item.getUnionId());
            });

            // 热更代码 start
            // 校验商会成员数据
            try {
                StringBuilder sb = new StringBuilder();
                for (PeakSeacraftProto.PeakSeacraftUnionMemberInfo memberInfo : item.getMemberInfoListList()) {
                    sb.append(memberInfo.getUserId()).append(",");
                }
                logger.info("巅峰海上争霸 收到来着区服的联盟数据 activityId:{},unionId:{},memberNum:{},memberList:{}", activityId, item.getUnionId(), item.getMemberInfoListList().size(), sb.toString());
                long now = System.currentTimeMillis();
                if (item.getMemberInfoListList().size() <= 0) {
                    return;
                }
                Iterator<Long> memberIterator = unionInfo.getMemberMap().keySet().iterator();
                while (memberIterator.hasNext()) {
                    long userId = memberIterator.next();

                    boolean flag = false;
                    for (PeakSeacraftProto.PeakSeacraftUnionMemberInfo memberInfo : item.getMemberInfoListList()) {
                        if (memberInfo.getUserId() == userId) {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        // 移除联盟成员
                        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
                        if (userInfo != null) {
                            unionInfo.getUnionData().setUpdateOption();
                            userInfo.getBaseData().setUnionId("");
                            memberIterator.remove();
                        }
                        logger.error("同步锁定联盟的联盟成员给跨服 时，校验数据，移除不在联盟的玩家数据， 玩家:{}", userId);
                    }
                }
                unionInfo.refreshUnionDonateExp();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 热更代码 end
        }
    }


    /**
     * @param userTeamInfoList
     */
    public void synUserTeamInfo(List<PeakSeacraftProto.PeakSeacraftLockUserInfo> userTeamInfoList) {
        long now = DateHelper.getCurrentTime();
        for (PeakSeacraftProto.PeakSeacraftLockUserInfo lockUserInfo : userTeamInfoList) {
            PeakSeacraftCrossUserInfo userInfo = getUserInfo(lockUserInfo.getUserId());
            if (userInfo != null) {
                if (lockUserInfo.hasPlayerInfo()) {
                    CrossUserMgr.updateUserBaseInfo(lockUserInfo.getUserId(), PlayerBasePb.parseToUserBaseInfo(lockUserInfo.getPlayerInfo()));
                }
                for (PeakSeacraftProto.PeakSeacraftLockTeamInfo item : lockUserInfo.getTeamInfoList()) {
                    PeakSeacraftTeamInfo teamInfo = new PeakSeacraftTeamInfo();
                    for (PeakSeacraftProto.PeakSeacraftPatronsEntity patronsEntity : item.getPatronsList()) {
                        teamInfo.getTeamList().add(parseSouthSeaPatronsInfo(patronsEntity));
                    }
                    teamInfo.setType(item.getType());
                    userInfo.getBaseData().getShipMemberMap().put(item.getType(), teamInfo);
                    userInfo.getBaseData().setUpdateOption();
                    // 船员小队组队日志
                    addLogPeakSeacraftTeam(userInfo, teamInfo, item.getType(), now);
                }
            }
        }
    }

    /**
     * 区服索要 联盟数据 和联盟成员的门客数据
     */
    public synchronized void synUnionInfo() {
        int round = getCurRound();
        if (round <= 0) {
            return;
        }
        // 返回需要同步的联盟数据
        List<String> returnUnionInfoList = new ArrayList<>();
        // 返回需要同步的玩家门客队伍数据
        Set<Long> returnUserTeamList = new HashSet<>();
        // 需要晋级上来所有联盟的数据
        synchronized (rankList) {
            for (PeakSeacraftUnionInfo unionInfo : rankList) {
                if (!unionInfo.isSynUnionInfo()) {
                    // 判断是否需要同步联盟数据
                    returnUnionInfoList.add(unionInfo.getUnionData().getUnionId());
                }
                for (PeakSeacraftCrossUserInfo userInfo : unionInfo.getMemberMap().values()) {
                    if (userInfo.getBaseData().getShipMemberMap().size() == 0) {
                        returnUserTeamList.add(userInfo.getBaseData().getUserId());
                    }
                }
            }
        }

        if (returnUnionInfoList.size() > 0) {
            isSyn.set(false);
        } else {
            if (rankList.size() > 0) {
                isSyn.compareAndSet(false, true);
            }
        }
        if (returnUnionInfoList.size() > 0 || returnUserTeamList.size() > 0) {
            // 去各个区服锁定 联盟成员
            ActivityInfo activityInfo = config.getActivityInfo();
            if (activityInfo != null) {
                PeakSeacraftProto.PeakSeacraftSynPromotionUnionCrossToGameMsg.Builder builder = getPromotionUnion();
                builder.addAllReturnUnionInfoList(returnUnionInfoList);
                builder.addAllReturnUserTeamList(returnUserTeamList);
                for (Long serverId : activityInfo.getServerIdList()) {
                    MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_LOCK_JOIN_UNION_FROM_CROSS, builder.setUnionGroup(unionGroup)));
                }
            }
        }
    }


    /**
     * 进入南海丝路
     */
    public PeakSeacraftProto.PeakSeacraftEnterRespMsg.Builder southSeaEnter(long userId, long refreshTime, String unionId) {
        PeakSeacraftProto.PeakSeacraftEnterRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftEnterRespMsg.newBuilder();
        builder.setRank(getUserRank(userId));
        builder.setRefreshTime(DateHelper.getCurrentTime());

        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (null != unionInfo) {
            builder.setInArea(unionInfo.getUnionData().getArea());
            builder.setInGroup(unionInfo.getUnionData().getGroupNum());
        }

        synchronized (areaGroupMap) {
            areaGroupMap.forEach((area, groupPeakSeacraftGroupInfoMap) -> {
                PeakSeacraftProto.PeakSeacraftGroupInfoTemp.Builder areaMsgTemp = PeakSeacraftProto.PeakSeacraftGroupInfoTemp.newBuilder();
                areaMsgTemp.setArea(area);
                AtomicInteger unionAmount = new AtomicInteger(0);
                groupPeakSeacraftGroupInfoMap.forEach((group, peakSeacraftGroupInfo) -> {
                    unionAmount.addAndGet(peakSeacraftGroupInfo.getUnionAmount());
                    areaMsgTemp.addGroup(group);
                });
                areaMsgTemp.setUnionCount(unionAmount.get());

                builder.addAreaGroup(areaMsgTemp);
            });
        }


        builder.setRet(0);
        return builder;
    }

    /**
     * 获取分组内船只数据
     */
    public PeakSeacraftProto.PeakSeacraftGetGroupDetailRespMsg.Builder getAreaGroupShipList(String unionId, int area, int group, long userId, long refreshTime) {
        PeakSeacraftProto.PeakSeacraftGetGroupDetailRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetGroupDetailRespMsg.newBuilder();
        builder.setRet(0);
        builder.setRank(getUserRank(userId));
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(area, group, false);
        if (null == groupInfo) {
            return builder.setRet(GameErrorCode.E_ERROR_DATA);
        }
        int key = area * 100 + group;
        if (refreshTime == 0 && lastMarqueeInfo.containsKey(key)) {
            builder.setMarqueeInfo(lastMarqueeInfo.get(key));
        }

        long now = DateHelper.getCurrentTime();
        builder.setRefreshTime(now);
        synchronized (groupInfo) {
            groupInfo.refreshCurJoinUnionShip();
            for (PeakSeacraftUnionInfo item : groupInfo.getUnionInfoList()) {
                if (item.getShipData() != null) {
                    if (item.getShipData().getRefreshTime() > refreshTime) {
                        item.refreshFixShip(now);
                        builder.addShipInfoList(item.builderPeakSeacraftShipInfo());
                    }
                }
            }
        }

        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(unionId);
        PeakSeacraftActivityConfig activityConfig = config;
        //同海域同组的才发这部分
        if (unionInfo != null && unionInfo.getUnionData().getArea() == area && unionInfo.getUnionData().getGroupNum() == group && activityConfig != null) {
            // 我方商会进攻目标
            List<PeakSeacraftBattleDetailData> list = new ArrayList<>(unionInfo.getAttackBattleMap().values());
            for (PeakSeacraftBattleDetailData item : list) {
                calTotalDamage(item);
            }
            list.sort((t1, t2) -> {
                if (t1.getTotalDamage() != t2.getTotalDamage()) {
                    return Long.compare(t2.getTotalDamage(), t1.getTotalDamage());
                } else {
                    return Long.compare(t1.getTime(), t2.getTime());
                }
            });
            int num = Math.min(list.size(), activityConfig.getAttackRankList().get(0));
            for (int i = 0; i < num; i++) {
                builder.addAttackUnionList(list.get(i).getTargetUnionId());
            }
            // 进攻我方的敌方商会
            list = new ArrayList<>(unionInfo.getDefendBattleMap().values());
            for (PeakSeacraftBattleDetailData item : list) {
                calTotalDamage(item);
            }
            list.sort((t1, t2) -> {
                if (t1.getTotalDamage() != t2.getTotalDamage()) {
                    return Long.compare(t2.getTotalDamage(), t1.getTotalDamage());
                } else {
                    return Long.compare(t1.getTime(), t2.getTime());
                }
            });
            num = Math.min(list.size(), activityConfig.getAttackRankList().get(1));
            for (int i = 0; i < num; i++) {
                builder.addUnderAttackUnionList(list.get(i).getTargetUnionId());
            }
        }
        return builder;
    }

    /**
     * 竞猜成功
     *
     */
    public void guessSuccess(boolean isBroadcast) {

        int guessRound = 1;
        for (PeakSeacraftCrossUserGuessData guessData : userGuessDataMap.values()) {
            PeakSeacraftGuessInfo southSeaGuessInfo = guessData.getGuessMap().get(guessRound);
            if (null != southSeaGuessInfo) {
                // 猜中的档位
                int guessId = getGuessSuccessId(guessData.getUserId());

                Map<Integer, List<Long>> map = guessTimesMap.get(guessRound);
                if (map == null) {
                    map = new ConcurrentHashMap<>();
                    guessTimesMap.put(guessRound, map);
                }
                List<Long> list = map.get(guessId);
                if (list == null) {
                    list = new ArrayList<>();
                    map.put(guessId, list);
                }
                list.add(guessData.getUserId());
                if (isBroadcast) {
                    PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.Builder broadcast = PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.newBuilder();
                    broadcast.setType(3);
                    broadcast.setGuessInfo(PeakSeacraftProto.PeakSeacraftGuessInfo.newBuilder().setRound(guessRound).addAllUnionList(southSeaGuessInfo.getUnionList()).setIsReceive(false).setNum(guessId));
                    MessageHelper.sendPacket(guessData.getServerId(), guessData.getUserId(), YanQuMessageUtils.buildMessage(ClientProtocol.U_PEAK_SEACRAFT_BROADCAST, broadcast));
                }
            }
        }
    }

    /**
     * 船只到达刷新任务
     */
    public void arrivalTask() {
        PeakSeacraftActivityConfig activityConfig = config;
        if (config == null) {
            return;
        }

        int activityCurRound = getActivityCurRound();
        if (activityCurRound < 1 || activityCurRound > activityConfig.getMaxRoundCount()) {
            return;
        }
        int round = activityCurRound;
        long now = DateHelper.getCurrentTime();

        if (!PeakSeacraftMgr.inRoundTime(activityId, round, now)) {
            return;
        }
        refreshUnionRank();
        for (PeakSeacraftUnionInfo item : rankList) {
            if (item.getUnionData().getRound() == activityCurRound && item.getShipData() != null) {
                // 如果到达了 未广播则广播
                if (item.getShipData().getEndTime() > 0 && !item.getUnionData().getResultMap().containsKey(round)) {
                    item.arrivalBroadcast(this);
                }
//              logger.info("当前船只unionId:{},名称：{}，未抵达，上一轮rank :{},已行驶距离：{}", item.getUnionData().getUnionId(), item.getUnionData().getUnionBaseInfo().getUnionName(), item.getUnionData().getRank(), item.getDistance((int) (crossActivityDetail.getParam1()), now));
            }
        }
    }

    public PeakSeacraftUnionInfo getUnionInfo(String unionId, boolean newIfNull) {
        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(unionId);
        if (unionInfo == null && newIfNull) {
            if (!StringUtils.isNullOrEmpty(unionId)) {
                synchronized (unionInfoMap) {
                    unionInfo = unionInfoMap.get(unionId);
                    if (unionInfo == null) {
                        PeakSeacraftCrossUnionData unionData = new PeakSeacraftCrossUnionData(activityId, unionGroup, unionId);

                        unionInfo = new PeakSeacraftUnionInfo(unionData);
                        unionInfoMap.put(unionId, unionInfo);
                    }
                }
            }
        }
        return unionInfo;
    }

    //获取榜首N名商会的UId
    public List<String> getRankTop(int lowestRank) {
        List<String> topList = new ArrayList<>();
        Map<Integer, String> topInfo = new ConcurrentHashMap<>();
        for (Map.Entry<String, PeakSeacraftUnionInfo> infoEntry : unionInfoMap.entrySet()) {
            int tmpRank = infoEntry.getValue().getUnionData().getRank();
            if (tmpRank > 0 && tmpRank <= lowestRank) {
                topInfo.put(tmpRank, infoEntry.getValue().getUnionData().getUnionId());
            }
        }
        if (topInfo.size() > lowestRank) {
            logger.info("海上争霸活动 activityId = {},前{}名内有{}个玩家,存在数据异常", activityId, lowestRank, topInfo.size());
            return null;
        }
        int rankNum = lowestRank <= topInfo.size() ? lowestRank : topInfo.size();
        for (int i = 1; i <= rankNum; i++) {
            if (StringUtils.isNullOrEmpty(topInfo.get(i))) {
                logger.info("海上争霸活动 activityId = {},第{}名没有玩家,存在数据异常", activityId, i);
                return null;
            } else {
                topList.add(topInfo.get(i));
            }
        }

        return topList;
    }

    /**
     * 组装玩家数据
     *
     * @param userId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftUserInfo.Builder getPeakSeacraftUserInfo(long userId, String unionId, long serverId) {
        PeakSeacraftProto.PeakSeacraftUserInfo.Builder builder = PeakSeacraftProto.PeakSeacraftUserInfo.newBuilder();
        PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(userId);
        if (userInfo != null) {
            refreshUser(userInfo);
            for (Map.Entry<Integer, PeakSeacraftTeamInfo> entry : userInfo.getBaseData().getShipMemberMap().entrySet()) {
                PeakSeacraftProto.PeakSeacraftShipTeamInfo.Builder teamInfo = PeakSeacraftProto.PeakSeacraftShipTeamInfo.newBuilder();
                teamInfo.setType(entry.getKey());
                teamInfo.setAttackTimes(entry.getValue().getTimes());
                teamInfo.setRaidAttackTimes(entry.getValue().getRaidTimes());
                for (PeakSeacraftPatronsInfo item : entry.getValue().getTeamList()) {
                    teamInfo.addPatronsId(item.getId());
                }
                builder.addShipTeamList(teamInfo);
            }
            builder.setRaidAttackTimes(userInfo.getBaseData().getRaidAttackTimes());
            builder.setRound(userInfo.getBaseData().getRound());
            if (userInfo.getChallengeData() != null) {
                builder.setUnionId(userInfo.getChallengeData().getTargetId());
            }

            builder.setRank(getUserRank(userId));
            builder.setAllScore(getUserScore(userId));

            PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
            if (null != unionInfo) {
                //更新到达海域成就
                notifyUpdateUserCondition(serverId, userId, unionInfo.getUnionData().getArea());
            }
        }

        //竞猜信息
        PeakSeacraftCrossUserGuessData userGuessData = getUserGuessData(userId, false);
        if (null != userGuessData) {
            for (Map.Entry<Integer, PeakSeacraftGuessInfo> entry : userGuessData.getGuessMap().entrySet()) {
                int num = getGuessSuccessId(userId);
                builder.addGuessList(PeakSeacraftProto.PeakSeacraftGuessInfo.newBuilder().setRound(entry.getKey()).addAllUnionList(entry.getValue().getUnionList()).setIsReceive(entry.getValue().isReceive()).setNum(num));
            }
        }

        return builder;
    }

    /**
     * 获取自己联盟的船只信息
     */
    public PeakSeacraftProto.PeakSeacraftShipInfo.Builder getUnionShip(long userId) {
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            return null;
        }
        if (StringUtils.isNullOrEmpty(userInfo.getBaseData().getUnionId())) {
            return null;
        }
        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(userInfo.getBaseData().getUnionId());
        if (unionInfo == null) {
            return null;
        }
        if (unionInfo.getShipData() == null) {
            return null;
        }
        return unionInfo.builderPeakSeacraftShipInfo();
    }

    /**
     * 捐献 游戏服就扣材料加经验在玩家身上,然后同步到跨服,游戏服需要判断自身联盟是否在名单中
     *
     * @param userId
     * @param serverId
     * @param unionId
     * @return
     */
    public void donationShip(long userId, long serverId, String unionId, int userTotalExp, int type, String cost) {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return;
        }
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (null == unionInfo) {
            return;
        }
        int oldValue = 0;
        int newValue = 0;
        int addValue = 0;
        int unionOldValue = 0;
        int unionNewValue = 0;
        synchronized (unionInfo) {
            PeakSeacraftCrossUserInfo memberInfo = unionInfo.getMember(userId);
            if (null == memberInfo) {
                return;
            }
            oldValue = memberInfo.getBaseData().getDonateExp();
            newValue = userTotalExp;
            addValue = newValue - oldValue;
            unionOldValue = unionInfo.getUnionData().getTotalDonationExp();
            memberInfo.getBaseData().setDonateExp(userTotalExp);

            unionInfo.refreshUnionDonateExp();

            unionNewValue = unionInfo.getUnionData().getTotalDonationExp();
        }

        // 加日志
        CrossAutoLogMgr.add(new LogPeakSeacraftDonation(activityId, userId, unionId,
                unionInfo.getUnionData().getArea(), unionInfo.getUnionData().getGroupNum(), type, cost,
                addValue, oldValue, newValue, unionOldValue, unionNewValue));
    }

    /**
     * 查看船只捐献详情
     *
     * @param userId
     * @param unionId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetDonationShipDetailRespMsg.Builder getDonationShipDetail(long userId, String unionId) {
        PeakSeacraftProto.PeakSeacraftGetDonationShipDetailRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetDonationShipDetailRespMsg.newBuilder();
        if (!StringUtils.isNullOrEmpty(unionId)) {
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
            if (unionInfo != null) {
                for (PeakSeacraftCrossUserInfo item : unionInfo.getMemberMap().values()) {
                    int donateExp = item.getBaseData().getDonateExp();
                    if (donateExp > 0) {
                        PeakSeacraftProto.PeakSeacraftDonationDetail.Builder detail = PeakSeacraftProto.PeakSeacraftDonationDetail.newBuilder();
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(item.getBaseData().getUserId());
                        if (userBaseInfo != null) {
                            detail.setMemberName(userBaseInfo.getNickName());
                        }
                        detail.setValue(donateExp);
                        builder.addDonationDetailList(detail);
                    }
                }
            }
        } else {
            PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
            if (userInfo != null) {
                int donateExp = userInfo.getBaseData().getDonateExp();
                if (donateExp > 0) {
                    PeakSeacraftProto.PeakSeacraftDonationDetail.Builder detail = PeakSeacraftProto.PeakSeacraftDonationDetail.newBuilder();
                    UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userInfo.getBaseData().getUserId());
                    if (userBaseInfo != null) {
                        detail.setMemberName(userBaseInfo.getNickName());
                    }
                    detail.setValue(donateExp);
                    builder.addDonationDetailList(detail);
                }
            }
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 查看船只详情
     *
     * @param unionId
     */
    public PeakSeacraftProto.PeakSeacraftGetShipRecordRespMsg.Builder getShipRecord(String unionId, int type) {
        PeakSeacraftProto.PeakSeacraftGetShipRecordRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetShipRecordRespMsg.newBuilder();
        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(unionId);
        if (unionInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_SHIP_NOT_EXIST);
            return builder;
        }
        List<PeakSeacraftCrossRecordData> recordList = new ArrayList<>();
        if (type == 0) {
            recordList = new ArrayList<>(unionInfo.getAttackRecordList());
        } else if (type == 1) {
            recordList = new ArrayList<>(unionInfo.getDefendRecordList());
        }
        for (PeakSeacraftCrossRecordData item : recordList) {
            builder.addAttackRecordList(builderPeakSeacraftShipRecordInfo(item));
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 南海丝路 进攻 / 突袭 / 使用道具进攻 / 修复
     *
     * @param type          0 进攻 1突袭 2使用道具进攻 3修复 5 使用船桨
     * @param userId        操作的玩家id
     * @param ownUnionId    执行者的联盟id
     * @param targetUnionId 目标联盟id
     * @param titleId       玩家等级
     * @param dispatchType  派遣小队类型
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftActionRespMsg.Builder action(int type, long userId, long serverId, String ownUnionId, String targetUnionId, int titleId, int dispatchType, int count, long preReduceCount, int propId) {
        PeakSeacraftProto.PeakSeacraftActionRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftActionRespMsg.newBuilder();
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_CONFIG);
            return builder;
        }
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_PROMOTION);
            return builder;
        }
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        // 自己的联盟没有晋级 不能执行
        if (unionInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_PROMOTION);
            return builder;
        }

        PeakSeacraftGroupInfo groupInfo = getGroupInfo(unionInfo.getUnionData().getArea(), unionInfo.getUnionData().getGroupNum(), false);
        if (null == groupInfo) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            return builder;
        }
        synchronized (groupInfo) {
            refreshUser(userInfo);
            groupInfo.sortUnionList(this);
            return groupInfo.action(this, userInfo, type, userId, targetUnionId, titleId, dispatchType, count, preReduceCount, propId);
        }
    }


    /**
     * 购买buff
     *
     * @param userId
     * @param buffId
     */
    public PeakSeacraftProto.PeakSeacraftBuyBuffRespMsg.Builder buyBuff(long userId, int buffId, int preReduceCount) {
        PeakSeacraftProto.PeakSeacraftBuyBuffRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftBuyBuffRespMsg.newBuilder();
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_CONFIG);
            return builder;
        }
        if (userInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
            return builder;
        }
        // 需要刷新玩家数据。 有可能进入下一轮 挑战还在
        synchronized (userInfo) {
            refreshUser(userInfo);
            if (userInfo.getChallengeData() == null || StringUtils.isNullOrEmpty(userInfo.getChallengeData().getTargetId())) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
                return builder;
            }
            if (userInfo.getChallengeData().getBuyBuffId() > 0) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_BUY_BUFF);
                return builder;
            }
            int addValue = 0;
            // 判断是否 首次购买过
            boolean firstBuy = getBuyBuffValue(userInfo) <= 0 && userInfo.getChallengeData().getWinStreakNum() <= 0;
            int needNum = 0;
            if (firstBuy) {
                // 首次购买
                if (activityConfig.firstBuyCostList.size() < buffId) {
                    builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_BUFF_NO_EXIST);
                    return builder;
                }
                addValue = activityConfig.firstAddBuffList.get(buffId - 1);
                needNum = activityConfig.firstBuyCostList.get(buffId - 1);
            } else {
                if (activityConfig.buyCostList.size() < buffId) {
                    builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_BUFF_NO_EXIST);
                    return builder;
                }
                addValue = activityConfig.addBuffList.get(buffId - 1);
                needNum = activityConfig.buyCostList.get(buffId - 1);
            }
            if (needNum > preReduceCount) {
                builder.setRet(GameErrorCode.E_BAG_INGOTS_NO_ENOUGH);
                return builder;
            }
            addBuffToTeam(userInfo, buffId, addValue);
            builder.setChallengeInfo(builderPeakSeacraftChallengeInfo(userInfo));
            builder.setCostNum(needNum);
        }

        builder.setRet(0);
        return builder;
    }


    /**
     * 挑战
     *
     * @param userId
     * @param targetId
     */
    public PeakSeacraftProto.PeakSeacraftChallengeRespMsg.Builder challenge(long userId, long targetId, int type, int blood, int buffId, long goldNum) {
        PeakSeacraftProto.PeakSeacraftChallengeRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftChallengeRespMsg.newBuilder();
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_CONFIG);
            return builder;
        }

        PeakSeacraftCrossUserInfo attacker = getUserInfo(userId);
        if (attacker == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
            return builder;
        }
        refreshUser(attacker);
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(attacker.getBaseData().getUnionId(), false);
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(unionInfo.getUnionData().getArea(), unionInfo.getUnionData().getGroupNum(), false);
        if (null == groupInfo) {
            builder.setRet(GameErrorCode.E_ERROR_DATA);
            return builder;
        }
        synchronized (groupInfo) {
            if (attacker.getChallengeData() == null || StringUtils.isNullOrEmpty(attacker.getChallengeData().getTargetId())) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
                return builder;
            }
            PeakSeacraftUnionInfo targetUnion = getUnionInfo(attacker.getChallengeData().getTargetId(), false);
            if (targetUnion == null) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
                return builder;
            }

            if (unionInfo.getUnionData().getArea() != targetUnion.getUnionData().getArea() ||
                    unionInfo.getUnionData().getGroupNum() != targetUnion.getUnionData().getGroupNum()) {
                attacker.setChallengeData(null);
                builder.setRet(GameErrorCode.E_PEAK_SEACRAFT_NOT_IN_SAME_GROUP);
                return builder;
            }

            return targetUnion.challenged(this, attacker, targetId, type, blood, buffId, goldNum);
        }
    }

    /**
     * 获取挑战信息
     *
     * @param userId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetChallengeRespMsg.Builder getChallengeInfo(long userId) {
        PeakSeacraftProto.PeakSeacraftGetChallengeRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetChallengeRespMsg.newBuilder();
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
            return builder;
        }
        refreshUser(userInfo);
        if (userInfo.getChallengeData() == null || StringUtils.isNullOrEmpty(userInfo.getChallengeData().getTargetId())) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
            return builder;
        }
        builder.setChallengeInfo(builderPeakSeacraftChallengeInfo(userInfo));
        builder.setRet(0);
        return builder;
    }


    /**
     * 领取连胜奖励
     *
     * @param userId
     */
    public PeakSeacraftProto.PeakSeacraftReceiveWinStreakRewardRespMsg.Builder receiveWinStreakReward(long userId) {
        PeakSeacraftProto.PeakSeacraftReceiveWinStreakRewardRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftReceiveWinStreakRewardRespMsg.newBuilder();
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
            return builder;
        }
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        if (unionInfo == null) {
            return builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
        }
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(unionInfo.getUnionData().getArea(), unionInfo.getUnionData().getGroupNum(), false);
        synchronized (groupInfo) {
            // 刷新
            refreshUser(userInfo);
            if (userInfo.getChallengeData() == null || StringUtils.isNullOrEmpty(userInfo.getChallengeData().getTargetId())) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NOT_HAS_CHALLENGE);
                return builder;
            }
            // 获取奖励
            if (!canRecWinStreakReward(userInfo)) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_REWARD);
                return builder;
            }
            PeakSeacraftActivityConfig activityConfig = config;
            // 连胜奖励
            int type = userInfo.getChallengeData().getAttackType() == 0 ? 1 : 2;

            int round = getCurRound();
            int boxId = activityConfig.getWinStreakReward(round, type, userInfo.getChallengeData().getTargetUnionGroupRank(), userInfo.getChallengeData().getWinStreakNum());
            if (boxId == 0) {
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_REWARD);
                return builder;
            }

            // 连胜奖励
            userInfo.getChallengeData().setReceiveWinStreakTimes(userInfo.getChallengeData().getWinStreakNum());
            // 领取奖励
            OpenGoodsBagResult openResult = TempGoodsBagMgr.getRandomGoods(boxId);
            builder.setReward(PropertyHelper.parsePropertyToString(openResult.getReward()));
            userInfo.getChallengeData().getWinStreakReward().addProperty(openResult.getReward());
            userInfo.getChallengeData().setUpdateOption();
            //随机两次奖励给客户端
            for (int i = 0; i < 2; i++) {
                OpenGoodsBagResult tempResult = TempGoodsBagMgr.getRandomGoods(boxId);
                builder.addOtherRewards(PropertyHelper.parsePropertyToString(tempResult.getReward()));
            }
            // 判断是否结算
            PeakSeacraftProto.PeakSeacraftChallengeResult.Builder challengeResult = settlement(userInfo, false);
            if (challengeResult != null) {
                builder.setResult(challengeResult);
            }
            builder.setBoxId(boxId);
            builder.setRet(0);
        }
        return builder;
    }

    /**
     * 领取竞猜奖励
     *
     * @param userId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftReceiveGuessRewardCrossToGameMsg.Builder receiveGuessReward(long userId) {
        PeakSeacraftProto.PeakSeacraftReceiveGuessRewardCrossToGameMsg.Builder builder = PeakSeacraftProto.PeakSeacraftReceiveGuessRewardCrossToGameMsg.newBuilder();

        if (getCurRound() <= config.getMaxRoundCount()) {
            //还没结束
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_GUESS_REWARD);
            return builder;
        }
        PeakSeacraftCrossUserGuessData userGuessData = getUserGuessData(userId, false);
        if (null == userGuessData) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_GUESS);
            return builder;
        }
        PeakSeacraftGuessInfo guessInfo = userGuessData.getGuessMap().get(1);
        if (guessInfo == null || guessInfo.getUnionList().size() == 0) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_GUESS);
            return builder;
        }
        if (guessInfo.isReceive()) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_RECEIVED_GUESS_REWARD);
            return builder;
        }
        //猜中档位
        int guessId = getGuessSuccessId(userId);
        builder.setRet(0);
        builder.setNum(guessId);
        guessInfo.setReceive(true);
        userGuessData.setUpdateOption();
        return builder;
    }

    /**
     * 玩家猜的商会ID转换为排名
     */
    private List<Integer> getUserGuessRankList(long userId) {
        List<Integer> guessRanks = new ArrayList<>();
        if (getCurRound() > config.getMaxRoundCount()) {
            PeakSeacraftCrossUserGuessData userGuessData = getUserGuessData(userId, false);
            if (null != userGuessData) {
                PeakSeacraftGuessInfo guessInfo = userGuessData.getGuessMap().get(1);
                if (null != guessInfo && guessInfo.getUnionList() != null) {
                    for (int i = 0; i < guessInfo.getUnionList().size(); i++) {
                        int guessRank = i + 1;
                        String guessUnionId = guessInfo.getUnionList().get(i);
                        PeakSeacraftUnionInfo unionInfo = getUnionInfo(guessUnionId, false);
                        if (null != unionInfo && unionInfo.getUnionData().getRank() == guessRank) {
                            guessRanks.add(guessRank);
                        }
                    }
                }
            }
        }
        return guessRanks;
    }

    /**
     * 获取玩家猜中的档位
     *
     * @param userId
     * @return
     */
    public int getGuessSuccessId(long userId) {
        return config.getGuessConfigId(getUserGuessRankList(userId));
    }


    /**
     * 进入竞猜
     */
    public PeakSeacraftProto.PeakSeacraftEnterGuessRespMsg.Builder enterGuess() {
        PeakSeacraftProto.PeakSeacraftEnterGuessRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftEnterGuessRespMsg.newBuilder();
        if (!isSyn.get()) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_GUESS_INFO);
            return builder;
        }
        PeakSeacraftProto.PeakSeacraftGuessDetail.Builder guessDetail = PeakSeacraftProto.PeakSeacraftGuessDetail.newBuilder();
        guessDetail.setRound(1);
        int round = 1;
        // 参赛联盟信息
        Map<String, Integer> unionMap = guessMap.get(round);
        for (PeakSeacraftUnionInfo unionInfo : unionInfoMap.values()) {
            String unionId = unionInfo.getUnionData().getUnionId();
            PeakSeacraftProto.PeakSeacraftGuessUnionInfo.Builder guessUnionInfo = PeakSeacraftProto.PeakSeacraftGuessUnionInfo.newBuilder();
            guessUnionInfo.setUnionId(unionId);
            if (unionInfo.getUnionData().getUnionBaseInfo() != null) {
                guessUnionInfo.setUnionName(unionInfo.getUnionData().getUnionBaseInfo().getUnionName());
                guessUnionInfo.addAllUnionFlag(UnionHelper.getUnionFlag(unionInfo.getUnionData().getUnionBaseInfo()));
            }
            PeakSeacraftResultInfo resultInfo = unionInfo.getUnionData().getResultMap().get(round);
            if (resultInfo != null) {
                guessUnionInfo.setRank(resultInfo.getRank());
            }else {
                guessUnionInfo.setRank(unionInfo.getUnionData().getRank());
            }
            if (unionMap != null) {
                guessUnionInfo.setNum(unionMap.getOrDefault(unionId, 0));
            }
            guessDetail.addUnionList(guessUnionInfo);
        }
        // 猜中的数量
        Map<Integer, List<Long>> map = guessTimesMap.get(round);
        if (map != null) {
            for (Map.Entry<Integer, List<Long>> guessTimes : map.entrySet()) {
                guessDetail.addResult(PeakSeacraftProto.PeakSeacraftGuessResult.newBuilder().setTimes(guessTimes.getKey()).setNum(guessTimes.getValue().size()));
            }
        }
        // 下发该轮前n名联盟
        if (getCurRound() > config.getMaxRoundCount()) {
            int guessNum = config.getGuessUnionNum();
            for (int i = 0; i < rankList.size() && i < guessNum; i++) {
                PeakSeacraftUnionInfo unionInfo = rankList.get(i);
                guessDetail.addPromotionUnionList(unionInfo.getUnionData().getUnionId());
            }
        }
        builder.addGuessInfo(guessDetail);
        builder.setRet(0);
        return builder;
    }


    /**
     * 竞猜
     *
     * @param userId
     * @param unionId
     * @param serverId
     * @param unionList
     */
    public PeakSeacraftProto.PeakSeacraftGuessRespMsg.Builder guess(long userId, String unionId, long serverId, List<String> unionList) {
        PeakSeacraftProto.PeakSeacraftGuessRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGuessRespMsg.newBuilder();
        for (String item : unionList) {
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(item, false);
            if (unionInfo == null) {
                // 竞猜的联盟不存在
                builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_GUESS_UNION_ID_ERROR);
                return builder;
            }
        }
        int guessRound = 1;
        PeakSeacraftCrossUserGuessData guessData = getUserGuessData(userId, true);
        guessData.setServerId(serverId);
        PeakSeacraftGuessInfo guessInfo = guessData.getGuessMap().getOrDefault(guessRound, null);
        if (guessInfo == null) {
            guessInfo = new PeakSeacraftGuessInfo();
            guessInfo.setUnionList(new ArrayList<>());
            guessInfo.setReceive(false);
        }
        List<String> guessUnionList = guessInfo.getUnionList();
        if (guessUnionList != null && guessUnionList.size() > 0) {
            // 取消原来的竞猜累计
            guessUnionList.forEach(e -> {
                Map<String, Integer> map = guessMap.get(guessRound);
                int num = Math.max(0, map.getOrDefault(e, 0) - 1);
                map.put(e, num);
            });
        }
        // 加入竞猜
        unionList.forEach(e -> {
            Map<String, Integer> map = guessMap.get(guessRound);
            if (map == null) {
                map = new ConcurrentHashMap<>();
                guessMap.put(guessRound, map);
            }
            map.put(e, map.getOrDefault(e, 0) + 1);
        });
        guessInfo.setUnionList(unionList);
        guessData.updateGuessMap(guessRound, guessInfo);

        // 加日志
        CrossAutoLogMgr.add(new LogPeakSeacraftGuess(activityId, userId, guessRound, StringUtils.listToString(unionList, ",")));

        builder.setRet(0);
        return builder;
    }

    /**
     * 刷新玩家信息 出战次数 和挑战
     */
    private void refreshUser(PeakSeacraftCrossUserInfo userInfo) {
        int curRound = getCurRound();
        if (userInfo.getBaseData().getRound() < curRound) {
            userInfo.getBaseData().setRaidAttackTimes(0);
            userInfo.getBaseData().getShipMemberMap().values().forEach(e -> {
                e.setTimes(0);
                e.setRaidTimes(0);
            });
            clearChallengeData(userInfo);
            userInfo.getBaseData().setRound(curRound);
        }
    }

    /**
     * 清除挑战数据
     *
     * @param userInfo
     */
    public void clearChallengeData(PeakSeacraftCrossUserInfo userInfo) {
        if (userInfo.getChallengeData() != null) {
            userInfo.getChallengeData().setTargetId("");
            userInfo.getChallengeData().setAttackType(0);
            userInfo.getChallengeData().setTeamType(0);
            userInfo.getChallengeData().getPatronsInfoList().clear();
            userInfo.getChallengeData().setWinStreakNum(0);
            userInfo.getChallengeData().setReceiveWinStreakTimes(0);
            userInfo.getChallengeData().setBuyBuffId(0);
            userInfo.getChallengeData().getAttackedList().clear();
            userInfo.getChallengeData().getRandomMap().clear();
            userInfo.getChallengeData().getBuffValueList().clear();
            userInfo.getChallengeData().setLockDurable(0);
            userInfo.getChallengeData().setDeductDurable(0);
            userInfo.getChallengeData().setTotalScore(0);
            userInfo.getChallengeData().setDistance(0);
            userInfo.getChallengeData().setTargetDistance(0);
            userInfo.getChallengeData().getWinStreakReward().getGoods().clear();
            userInfo.getChallengeData().setKillPatronsNum(0);
            userInfo.getBaseData().setAttackNum(userInfo.getBaseData().getAttackNum() + 1);
        }
    }

    public long getTotalBlood(PeakSeacraftCrossUserInfo userInfo) {
        long totalBlood = 0;
        for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
            totalBlood += item.getMaxBlood();
        }
        return totalBlood;
    }

    public long getRemainBlood(PeakSeacraftCrossUserInfo userInfo) {
        long remainBlood = 0;
        for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
            remainBlood += item.getBlood();
        }
        return remainBlood;
    }

    public PeakSeacraftCrossUserInfo getUserInfo(long userId) {
        return userInfoMap.get(userId);
    }


    private PeakSeacraftCrossUserInfo initUserInfo(long userId, String unionId, long serverId, int position) {
        PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(userId);
        if (userInfo == null) {
            synchronized (userInfoMap) {
                userInfo = userInfoMap.get(userId);
                if (userInfo == null) {
                    PeakSeacraftCrossUserData userData = new PeakSeacraftCrossUserData(activityId, unionGroup, userId);
                    userData.setServerId(serverId);
                    userData.setUnionId(unionId);
                    userData.setUnionPosition(position);

                    userInfo = new PeakSeacraftCrossUserInfo(userData);
                    userInfoMap.put(userId, userInfo);
                    if (!StringUtils.isNullOrEmpty(unionId)) {
                        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, true);
                        unionInfo.getMemberMap().put(userId, userInfo);
                    }
                }
            }
        } else {
            userInfo.getBaseData().setUnionId(unionId);
            userInfo.getBaseData().setUnionPosition(position);
            userInfo.getBaseData().setServerId(serverId);
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
            if (null != unionInfo) {
                unionInfo.getUnionData().updateMemberPosition(userId, position);
            }
        }
        return userInfo;
    }

    private PeakSeacraftCrossUserGuessData getUserGuessData(long userId, boolean newIfNull) {
        PeakSeacraftCrossUserGuessData data = userGuessDataMap.get(userId);
        if (data == null && newIfNull) {
            synchronized (userGuessDataMap) {
                data = userGuessDataMap.get(userId);
                if (null == data) {
                    data = new PeakSeacraftCrossUserGuessData(activityId, unionGroup, userId);
                    data.setGuessMap(new ConcurrentHashMap<>());
                    userGuessDataMap.put(userId, data);
                }
            }
        }
        return data;
    }

    /**
     * 加入联盟 报名期才可以 待修改
     *
     * @param userId
     * @param unionId
     */
    public void joinUnion(long userId, String unionId) {
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null || StringUtils.isNullOrEmpty(unionId)) {
            return;
        }
        if (unionId.equals(userInfo.getBaseData().getUnionId())) {
            return;
        }
        // 移除原来操作
        PeakSeacraftUnionInfo oldUnionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        if (oldUnionInfo != null && oldUnionInfo.getMemberMap().containsKey(userId)) {
            oldUnionInfo.getMemberMap().remove(userId);
        }

        PeakSeacraftUnionInfo newUnionInfo = getUnionInfo(unionId, false);
        if (newUnionInfo != null && newUnionInfo.getMemberMap().containsKey(userId)) {
            newUnionInfo.getMemberMap().put(userId, userInfo);
        }
    }

    /**
     * 获取联盟晋级情况
     *
     * @return
     */
    public List<PeakSeacraftProto.PeakSeacraftResult> getPeakSeacraftResultList(String unionId) {
        List<PeakSeacraftProto.PeakSeacraftResult> resultList = new ArrayList<>();
        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(unionId);
        if (unionInfo != null) {
            resultList.addAll(getUnionResultList(unionInfo));
        }
        return resultList;
    }

    /**
     * 增加buff
     */
    public Set<Integer> addBuffToTeam(PeakSeacraftCrossUserInfo userInfo, int buffId, int addValue) {
        // 血量有加的门客id
        Set<Integer> set = new HashSet<>();
        userInfo.getChallengeData().setBuyBuffId(buffId);
        userInfo.getChallengeData().getBuffValueList().add(addValue);

        PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(userInfo.getBaseData().getUnionId());
        SeacraftSouthSeaShipConfig shipConfig = PeakSeacraftMgr.getShipConfig(unionInfo, true);
        long totalBlood = 0;
        for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
            totalBlood += (item.getEarn() + shipConfig.getBonus());
        }
        // 回复的血量
        long addBlood = totalBlood * addValue / 100;
        // 1先扩大上限 2先尝试 把每个门客的血量回满  3再复活
        userInfo.getChallengeData().getPatronsInfoList().forEach(e -> {
            long addMaxBlood = (e.getEarn() + shipConfig.getBonus()) * addValue / 100;
            e.setMaxBlood(e.getMaxBlood() + addMaxBlood);
        });

        for (int i = userInfo.getChallengeData().getPatronsInfoList().size() - 1; i >= 0; i--) {
            PeakSeacraftLockPatronsInfo patronsInfo = userInfo.getChallengeData().getPatronsInfoList().get(i);
            long diffBlood = patronsInfo.getMaxBlood() - patronsInfo.getBlood();
            if (diffBlood > 0) {
                set.add(patronsInfo.getId());
                if (addBlood > diffBlood) {
                    // 回满
                    patronsInfo.setBlood(patronsInfo.getMaxBlood());
                    addBlood -= diffBlood;
                } else {
                    patronsInfo.setBlood(patronsInfo.getBlood() + addBlood);
                    addBlood = 0;
                    break;
                }
            }
        }
        if (addBlood > 0) {
            // 复活门客
            for (int i = userInfo.getChallengeData().getPatronsInfoList().size() - 1; i >= 0; i--) {
                PeakSeacraftLockPatronsInfo patronsInfo = userInfo.getChallengeData().getPatronsInfoList().get(i);
                if (patronsInfo.getBlood() <= 0) {
                    set.add(patronsInfo.getId());
                    if (addBlood > patronsInfo.getMaxBlood()) {
                        patronsInfo.setBlood(patronsInfo.getMaxBlood());
                        addBlood -= patronsInfo.getMaxBlood();
                    } else {
                        patronsInfo.setBlood(patronsInfo.getBlood() + addBlood);
                        addBlood = 0;
                        break;
                    }
                }
            }
        }
        return set;
    }


    /**
     * 查看捐献情况
     */
    public PeakSeacraftProto.PeakSeacraftGetDonationShipRespMsg.Builder getUnionDonationShipList(long userId, String unionId) {
        PeakSeacraftProto.PeakSeacraftGetDonationShipRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetDonationShipRespMsg.newBuilder();
        if (!StringUtils.isNullOrEmpty(unionId)) {
            PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
            if (userInfo != null) {
                PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
                // 查看 联盟的捐献情况
                if (unionInfo != null) {
                    builder.setTotalDonateExp(unionInfo.getUnionData().getTotalDonationExp());
                    builder.setShipDonateExp(unionInfo.getShipDonateExp());
                    // 联盟成员捐献排行
                    for (PeakSeacraftCrossUserInfo memberInfo : unionInfo.getMemberMap().values()) {
                        int totalValue = memberInfo.getBaseData().getDonateExp();
                        if (totalValue > 0) {
                            PeakSeacraftProto.PeakSeacraftShipDonationInfo.Builder donationInfo = PeakSeacraftProto.PeakSeacraftShipDonationInfo.newBuilder();
                            donationInfo.setUserId(memberInfo.getBaseData().getUserId());
                            String userName = CrossUserMgr.getUserName(memberInfo.getBaseData().getUserId());
                            donationInfo.setUserName(userName);
                            donationInfo.setValue(totalValue);
                            builder.addDonationInfoList(donationInfo);
                        }
                    }
                }
            }
        } else {
            // 查看 自己的捐献情况
            PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(userId);
            if (userInfo != null) {
                builder.setTotalDonateExp(userInfo.getBaseData().getDonateExp());
            }
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 查看竞猜成功的玩家
     *
     * @param round
     * @param guessNum
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetGuessSuccessUserRespMsg.Builder getGuessSuccessUser(int round, int guessNum) {
        PeakSeacraftProto.PeakSeacraftGetGuessSuccessUserRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetGuessSuccessUserRespMsg.newBuilder();
        Map<Integer, List<Long>> timesMap = guessTimesMap.get(round);
        if (timesMap != null) {
            Set<Long> set = new HashSet<>();
            for (Map.Entry<Integer, List<Long>> entry : timesMap.entrySet()) {
                int tempGuessNum = entry.getKey();
                if (tempGuessNum == guessNum) {
                    set.addAll(entry.getValue());
                    break;
                }
            }
            for (Long userId : set) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                if (userBaseInfo != null) {
                    builder.addUserList(PeakSeacraftProto.PeakSeacraftGuessSuccessUserInfo.newBuilder().setServerId(userBaseInfo.getServerId()).setUserName(userBaseInfo.getNickName()));
                }
            }
        }
        builder.setRet(0);
        return builder;
    }


    /**
     * 查看玩家所在的联盟排名
     *
     * @param unionId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetUnionRankRespMsg.Builder getUnionRank(long userId, String unionId) {
        PeakSeacraftProto.PeakSeacraftGetUnionRankRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetUnionRankRespMsg.newBuilder();
        unionId = getUserUnionId(userId, unionId);
        int rank = getUnionRank(unionId);
        builder.setRank(rank);
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null && unionInfo.getShipData() != null) {
            builder.setArrivalTime(unionInfo.getShipData().getEndTime());
            builder.setArea(unionInfo.getUnionData().getArea());
            builder.setGroup(unionInfo.getUnionData().getGroupNum());
            builder.setGroupRank(unionInfo.getUnionData().getGroupRank());
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 查看联盟的排名
     *
     * @param unionId
     * @return
     */
    private int getUnionRank(String unionId) {
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo == null || unionInfo.getUnionData().getRound() <= 0) {
            return -1;
        }
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return -1;
        }

        int activityCurRound = getActivityCurRound();
        if (activityCurRound > activityConfig.getMaxRoundCount()) {
            // 活动已进入领奖期 排名已经固定
            return unionInfo.getUnionData().getRank();
        } else {
            // 实时去活动排名
            int rank = getUnionRank(unionInfo, true);
            if (rank == 0) {
                return -1;
            } else {
                return rank;
            }
        }
    }

    /**
     * 获取玩家所属于的联盟
     *
     * @return
     */
    private String getUserUnionId(long userId, String defaultUnionId) {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return "";
        }
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);

        int activityCurRound = getActivityCurRound();
        if (activityCurRound > activityConfig.getMaxRoundCount()) {
            // 锁榜
            if (userInfo == null) {
                return "";
            } else {
                return userInfo.getBaseData().getUnionId();
            }
        } else {
            if (userInfo == null) {
                return defaultUnionId;
            } else {
                return userInfo.getBaseData().getUnionId();
            }
        }

    }


    /**
     * 查看联盟排名列表
     *
     * @param userId
     */
    public PeakSeacraftProto.PeakSeacraftGetUnionRankListRespMsg.Builder getGroupUnionRankList(long userId, String unionId, int area, int group) {
        PeakSeacraftProto.PeakSeacraftGetUnionRankListRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetUnionRankListRespMsg.newBuilder();
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(area, group, false);
        if (null == groupInfo) {
            return builder.setRet(GameErrorCode.E_ERROR_DATA);
        }

        int activityCurRound = getActivityCurRound();
        int curRound = activityCurRound;

        synchronized (groupInfo) {
            groupInfo.sortUnionList(this);
            builder.addAllUnionRankList(groupInfo.buildUnionRankListMsg(this, curRound));
        }
        unionId = getUserUnionId(userId, unionId);
        builder.setUnionId(unionId);
        builder.setRet(0);
        builder.setArea(area);
        builder.setGroup(group);
        return builder;
    }

    /**
     * 查看商会南海丝路成员积分和抵达信息
     *
     * @param unionId
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetArrivalInfoRespMsg.Builder getArrivalInfo(String unionId) {
        PeakSeacraftProto.PeakSeacraftGetArrivalInfoRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetArrivalInfoRespMsg.newBuilder();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null) {
            for (PeakSeacraftCrossUserInfo item : unionInfo.getMemberMap().values()) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(item.getBaseData().getUserId());
                if (userBaseInfo != null) {
                    builder.addUserScoreList(PeakSeacraftProto.PeakSeacraftUserScoreInfo.newBuilder().setUserName(userBaseInfo.getNickName()).setScore(item.getBaseData().getScore()));
                }
            }
            builder.addAllResultList(getUnionResultList(unionInfo));
        }
        builder.setRet(0);
        return builder;
    }


    /**
     * 查看船只修复情况
     *
     * @param unionId
     */
    public PeakSeacraftProto.PeakSeacraftGetFixRankRespMsg.Builder getFixRank(String unionId) {
        PeakSeacraftProto.PeakSeacraftGetFixRankRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetFixRankRespMsg.newBuilder();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null) {
            for (Map.Entry<Long, PeakSeacraftFixDurableInfo> entry : unionInfo.getUnionData().getFixDurableMap().entrySet()) {
                PeakSeacraftProto.PeakSeacraftShipFixDurableInfo.Builder fixDurable = PeakSeacraftProto.PeakSeacraftShipFixDurableInfo.newBuilder();
                fixDurable.setUserId(entry.getKey());
                fixDurable.setValue(entry.getValue().getV());
                fixDurable.setTime(entry.getValue().getT());
                fixDurable.setUserName(CrossUserMgr.getUserName(entry.getKey()));
                builder.addFixInfoList(fixDurable);
            }
        }
        builder.setRet(0);
        return builder;
    }


    /**
     * 查看船只攻防信息
     *
     * @param unionId
     * @param type
     */
    public PeakSeacraftProto.PeakSeacraftGetBattleRecordRespMsg.Builder getBattleRecord(String unionId, int type) {
        PeakSeacraftProto.PeakSeacraftGetBattleRecordRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetBattleRecordRespMsg.newBuilder();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null) {
            builder.addAllRecordList(unionInfo.getBattleRecord(this, type));
        }
        builder.setRet(0);
        return builder;
    }


    /**
     * 查看船只成员详细攻防数据
     *
     * @param type
     * @param unionId
     * @param sonType
     * @return
     */
    public PeakSeacraftProto.PeakSeacraftGetMemberBattleDetailRespMsg.Builder getMemberBattleDetail(int type, String unionId, int sonType, String targetId) {
        PeakSeacraftProto.PeakSeacraftGetMemberBattleDetailRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetMemberBattleDetailRespMsg.newBuilder();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null) {
            builder.addAllRecordList(unionInfo.getMemberBattleDetail(this, type, sonType, targetId));
        }
        builder.setRet(0);
        return builder;
    }

    /**
     * 获取联盟 南海丝路晋级情况
     *
     * @param unionInfo
     * @return
     */
    private List<PeakSeacraftProto.PeakSeacraftResult> getUnionResultList(PeakSeacraftUnionInfo unionInfo) {
        List<PeakSeacraftProto.PeakSeacraftResult> list = new ArrayList<>();
        for (Map.Entry<Integer, PeakSeacraftResultInfo> entry : unionInfo.getUnionData().getResultMap().entrySet()) {
            int round = entry.getKey();
            list.add(parsePeakSeacraftResultProto(round, entry.getValue()));
        }
        return list;
    }

    private PeakSeacraftProto.PeakSeacraftResult parsePeakSeacraftResultProto(int round, PeakSeacraftResultInfo resultInfo) {
        PeakSeacraftProto.PeakSeacraftResult.Builder msg = PeakSeacraftProto.PeakSeacraftResult.newBuilder();
        msg.setRound(round).setRank(resultInfo.getRank()).setArriveTime(resultInfo.getArriveTime()).setDistance(resultInfo.getDistance()).
                setGroup(resultInfo.getGroup()).setGroupRank(resultInfo.getGroupRank()).setArea(resultInfo.getArea());
        return msg.build();
    }


    public int getCurRound() {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return 0;
        }
        ActivityInfo activityInfo = config.getActivityInfo();
        if (activityInfo == null) {
            return 0;
        }
        return config.getCurRound();
    }

    /**
     * 获得活动运行的回合
     *
     * @return
     */
    public int getActivityCurRound() {
        CrossActivityDetail crossActivityDetail = ActivityMgr.getCrossActivityDetail(activityId, unionGroup,true);
        return (int) (crossActivityDetail.getParam1());
    }

    /**
     * 更新活动运行的回合
     *
     * @return
     */
    public void setActivityCurRound(int round) {
        CrossActivityDetail crossActivityDetail = ActivityMgr.getCrossActivityDetail(activityId, unionGroup,true);
        crossActivityDetail.setParam1(round);
    }

    /**
     * 刷新当前晋级联盟的船只数据
     */
    public void refreshCurJoinUnionShip() {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            return;
        }
        int curRound = getActivityCurRound();
        if (curRound <= 0 || curRound > activityConfig.getMaxRoundCount()) {
            return;
        }
        long now = DateHelper.getCurrentTime();
        long roundStartTime = PeakSeacraftMgr.getRoundStartTime(activityId, curRound);
        if (now == 0 || now < roundStartTime) {
            return;
        }

        synchronized (rankList) {
            for (PeakSeacraftUnionInfo item : rankList) {
                item.initShip();
                item.resetShip(roundStartTime);
            }
        }
    }


    /**
     * 广播跑马灯
     *
     * @param userId
     * @param attackUnion
     * @param defendUnion
     * @param attackType
     * @param killNum
     * @param score
     * @param durable
     * @param goodsUseNum
     * @param time
     */
    public void broadcastPeakSeacraftMarqueeInfo(long userId, PeakSeacraftUnionInfo attackUnion, PeakSeacraftUnionInfo defendUnion, int attackType, int killNum, int score, int durable, int goodsUseNum, long time) {
        PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.Builder broadcast = PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.newBuilder();
        broadcast.setType(1);
        // 船只信息
        broadcast.setSeaShipInfo(defendUnion.builderPeakSeacraftShipInfo());
        // 跑马灯
        PeakSeacraftProto.PeakSeacraftMarqueeInfo.Builder marqueeInfo = PeakSeacraftProto.PeakSeacraftMarqueeInfo.newBuilder();
        marqueeInfo.setSonType(attackType);
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo != null) {
            marqueeInfo.setUserName(userBaseInfo.getNickName());
            marqueeInfo.setServerId(userBaseInfo.getServerId());
        }
        marqueeInfo.setUnionId(attackUnion.getUnionData().getUnionId());
        marqueeInfo.setUnionName(attackUnion.getUnionData().getUnionBaseInfo().getUnionName());
        marqueeInfo.setTargetUnionId(defendUnion.getUnionData().getUnionId());
        marqueeInfo.setTargetUnionName(defendUnion.getUnionData().getUnionBaseInfo().getUnionName());
        marqueeInfo.setTargetServerId(defendUnion.getUnionData().getUnionBaseInfo().getServerId());
        marqueeInfo.setScore(score);
        marqueeInfo.setKillNum(killNum);
        marqueeInfo.setDurable(durable);
        marqueeInfo.setGoodsUseNum(goodsUseNum);
        marqueeInfo.setTime(time);
        marqueeInfo.setArea(attackUnion.getUnionData().getArea());
        marqueeInfo.setGroup(attackUnion.getUnionData().getGroupNum());
        broadcast.setMarqueeInfo(marqueeInfo);

        int key = attackUnion.getUnionData().getArea() * 100 + attackUnion.getUnionData().getGroupNum();
        lastMarqueeInfo.put(key, marqueeInfo);

        PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.Builder toGameMsg = PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.newBuilder();
        toGameMsg.setBroadcastMsg(broadcast);
        toGameMsg.setArea(attackUnion.getUnionData().getArea());
        toGameMsg.setGroup(attackUnion.getUnionData().getGroupNum());
        toGameMsg.setActivityId(activityId);
        toGameMsg.setUnionGroup(unionGroup);

        config.getActivityInfo().getServerIdList().forEach(serverId -> {
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_BROADCAST_FROM_CROSS, toGameMsg));
        });
    }

    /**
     * 广播抵达信息
     */
    public void broadcastArrivalInfo(PeakSeacraftUnionInfo unionInfo, int round) {
        // 广播
        PeakSeacraftResultInfo resultInfo = unionInfo.getUnionData().getResultMap().get(round);
        if (resultInfo == null) {
            return;
        }

        PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.Builder broadcast = PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.newBuilder();
        broadcast.setType(2);
        broadcast.setResult(parsePeakSeacraftResultProto(round, resultInfo));

        PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.Builder toGameMsg = PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.newBuilder();
        toGameMsg.setBroadcastMsg(broadcast);
        toGameMsg.setArea(unionInfo.getUnionData().getArea());
        toGameMsg.setGroup(unionInfo.getUnionData().getGroupNum());
        toGameMsg.setActivityId(activityId);
        toGameMsg.setUnionGroup(unionGroup);
        Set<Long> serverIds = new ConcurrentHashSet<>();
        for (PeakSeacraftCrossUserInfo member : unionInfo.getMemberMap().values()) {
            serverIds.add(member.getBaseData().getServerId());
            toGameMsg.addNeedBroadcastIds(member.getBaseData().getUserId());
        }
        serverIds.forEach(serverId -> {
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_BROADCAST_FROM_CROSS, toGameMsg));
        });
    }

    /**
     * 获取玩家活动排名
     *
     * @param userId
     * @return
     */
    public int getUserRank(long userId) {
        int rank = -1;
        PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(userId);
        if (userInfo != null) {
            String rankType = String.valueOf(eGamePlayerEventType.PeakSeacraftUserScoreRank.getValue());
//            rank = CrossYRankMgr.getUserRankNum(CrossYRankMgr.getSortUserRankList(activityId, unionGroup, String.valueOf(eGamePlayerEventType.PeakSeacraftUserScoreRank.getValue())), userId);
            RankProto.RankListMsg.Builder rankBuilder = CrossYRankCacheMgr.getUserRankList(activityId, unionGroup, rankType);
            rank = CrossYRankCacheMgr.getUserRank(activityId, unionGroup, rankType, rankBuilder, userId);
        }
        return rank;
    }

    /**
     * 是否可以领取连胜奖励
     *
     * @param userInfo
     * @return
     */
    public boolean canRecWinStreakReward(PeakSeacraftCrossUserInfo userInfo) {
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig != null) {
            if (userInfo.getChallengeData().getWinStreakNum() != 0 && userInfo.getChallengeData().getWinStreakNum() != userInfo.getChallengeData().getReceiveWinStreakTimes() &&
                    userInfo.getChallengeData().getWinStreakNum() % activityConfig.getSEACRAFT_CRAFT_REWARD_COMBONUM() == 0) {
                // 到了可以领取连胜奖励的档位
                return true;
            }
        }
        return false;
    }

    /**
     * 挑战结算
     *
     * @param attacker
     */
    public PeakSeacraftProto.PeakSeacraftChallengeResult.Builder settlement(PeakSeacraftCrossUserInfo attacker, boolean forceSettlement) {
        PeakSeacraftProto.PeakSeacraftChallengeResult.Builder challengeResult = null;

        PeakSeacraftUnionInfo attackUnion = unionInfoMap.get(attacker.getBaseData().getUnionId());
        PeakSeacraftUnionInfo targetUnion = unionInfoMap.get(attacker.getChallengeData().getTargetId());
        boolean isWin = isKillAll(attacker, targetUnion);
        if (forceSettlement || (!canRecWinStreakReward(attacker) && isWin)) {
            long time = DateHelper.getCurrentTime();
            attackUnion.addRecord(0, attacker.getChallengeData().getAttackType(), attacker.getBaseData().getUserId(), attacker.getChallengeData().getTargetId(), attacker.getChallengeData().getWinStreakNum(), attacker.getChallengeData().getTotalScore(), attacker.getChallengeData().getDeductDurable(), 0, time, 0, 0, 0, config.getSEACRAFT_CRAFT_SHIP_NUM());
            targetUnion.addRecord(1, attacker.getChallengeData().getAttackType(), attacker.getBaseData().getUserId(), attacker.getBaseData().getUnionId(), attacker.getChallengeData().getWinStreakNum(), attacker.getChallengeData().getTotalScore(), attacker.getChallengeData().getDeductDurable(), 0, time, 0, 0, 0, config.getSEACRAFT_CRAFT_SHIP_NUM());

            // 加进攻 细节
            addBattleDetail(attackUnion, attacker.getBaseData().getUserId(), targetUnion, attacker.getChallengeData().getAttackType(), attacker.getChallengeData().getDeductDurable(), time);

            challengeResult = PeakSeacraftProto.PeakSeacraftChallengeResult.newBuilder();
            challengeResult.setTotalScore(attacker.getChallengeData().getTotalScore());
            challengeResult.setTotalDurable(attacker.getChallengeData().getDeductDurable());
            challengeResult.setKillNum(attacker.getChallengeData().getAttackedList().size());
            challengeResult.setWinStreakReward(PropertyHelper.parsePropertyToString(attacker.getChallengeData().getWinStreakReward()));
            challengeResult.setWinStreakNum(attacker.getChallengeData().getWinStreakNum());
            challengeResult.setUnionName(targetUnion.getUnionData().getUnionBaseInfo().getUnionName());
            challengeResult.setIsWin(isWin);
            challengeResult.setKillPatronsNum(attacker.getChallengeData().getKillPatronsNum());
            PeakSeacraftActivityConfig activityConfig = config;

            if (challengeResult.getTotalDurable() > 0 && challengeResult.getKillNum() >= activityConfig.getSEACRAFT_CRAFT_KILL_REPORT()) {
                broadcastPeakSeacraftMarqueeInfo(attacker.getBaseData().getUserId(), attackUnion, targetUnion, attacker.getChallengeData().getAttackType(), challengeResult.getKillNum(), challengeResult.getTotalScore(), challengeResult.getTotalDurable(), 0, time);
            }
            String reward = null;
            if (isKillAll(attacker, targetUnion)) {
                reward = activityConfig.battleRewardList.get(0);
            } else {
                reward = activityConfig.battleRewardList.get(1);
            }
            // 计算获得的勋章奖励
            int medalNum = getMedalNum(activityConfig, attacker);
            challengeResult.setGetMedalNum(medalNum);
            challengeResult.setBattleReward(reward);
            clearChallengeData(attacker);
        }

        return challengeResult;
    }

    /**
     * 是否全歼联盟玩家
     *
     * @return
     */
    public boolean isKillAll(PeakSeacraftCrossUserInfo attacker, PeakSeacraftUnionInfo targetUnion) {
        return attacker.getChallengeData().getAttackedList().size() >= targetUnion.getMemberMap().size();
    }

    /**
     * 获得勋章的数量
     *
     * @return
     */
    public int getMedalNum(PeakSeacraftActivityConfig activityConfig, PeakSeacraftCrossUserInfo attacker) {
        int medalNum = 0;
        if (attacker.getChallengeData() != null) {
            if (attacker.getChallengeData().getAttackType() == 0) {
                medalNum = activityConfig.getSEACRAFT_CRAFT_CHARGE_SCORE();
            } else {
                // 本次进攻消耗的进攻道具数量
                PeakSeacraftTeamInfo seaTeamInfo = attacker.getBaseData().getShipMemberMap().get(attacker.getChallengeData().getTeamType());
                // 判断消耗数量
                int consumeNum = 0;
                if (activityConfig.attackItemCostList.size() > seaTeamInfo.getTimes() - 1) {
                    consumeNum = activityConfig.attackItemCostList.get(seaTeamInfo.getTimes() - 1);
                }
                medalNum = activityConfig.attackScoreList.get(0) + activityConfig.attackScoreList.get(1) * consumeNum;
            }
        }
        return medalNum;
    }

    /**
     * 领取排行榜奖励
     *
     * @param userId
     * @return
     */
    public SeacraftSouthSeaProto.SeacraftSouthSeaReceiveUnionRankCrossToGameMsg.Builder receiveUnionRank(long userId) {
        SeacraftSouthSeaProto.SeacraftSouthSeaReceiveUnionRankCrossToGameMsg.Builder builder = SeacraftSouthSeaProto.SeacraftSouthSeaReceiveUnionRankCrossToGameMsg.newBuilder();
        int activityCurRound = getActivityCurRound();
        PeakSeacraftActivityConfig activityConfig = config;
        if (activityConfig == null) {
            builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_CONFIG);
            return builder;
        }
        int curRound = activityCurRound;
        if (curRound <= activityConfig.getMaxRoundCount()) {
            // 未结算
            builder.setRet(GameErrorCode.E_ACTIVITY_NO_IN_GET_REWARD_TIME);
            return builder;
        }
        int rank = -1;
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo != null) {
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
            if (unionInfo != null && unionInfo.getUnionData().getRound() > 0 && unionInfo.getUnionData().getMemberMap().containsKey(userId)) {
                rank = unionInfo.getUnionData().getRank();
                builder.setMasterId(unionInfo.getUnionData().getUnionBaseInfo().getMasterUserId());
                builder.setPosition(userInfo.getBaseData().getUnionPosition());
                builder.setUnionId(unionInfo.getUnionData().getUnionId());
            }
        }
        builder.setActivityId(activityId);
        builder.setRank(rank);
        builder.setRet(0);
        return builder;
    }

    /**
     * 查看联盟加速榜
     *
     * @param unionId
     * @return
     */
    public List<PeakSeacraftProto.PeakSeacraftSpeedUpRecordInfo> getSpeedUpRecord(String unionId) {
        List<PeakSeacraftProto.PeakSeacraftSpeedUpRecordInfo> list = new ArrayList<>();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null) {
            for (PeakSeacraftCrossUserInfo item : unionInfo.getMemberMap().values()) {
                if (item.getBaseData().getUseSpeedUpInfoMap().size() > 0) {
                    PeakSeacraftProto.PeakSeacraftSpeedUpRecordInfo.Builder recordInfo = PeakSeacraftProto.PeakSeacraftSpeedUpRecordInfo.newBuilder();
                    UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(item.getBaseData().getUserId());
                    if (userBaseInfo != null) {
                        recordInfo.setPlayerInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                    }
                    recordInfo.setUserId(item.getBaseData().getUserId());
                    for (PeakSeacraftUseSpeedUpInfo speedUpInfo : item.getBaseData().getUseSpeedUpInfoMap().values()) {
                        PeakSeacraftProto.PeakSeacraftUseSpeedUpPropInfo.Builder useSpeedUpPropInfo = PeakSeacraftProto.PeakSeacraftUseSpeedUpPropInfo.newBuilder();
                        useSpeedUpPropInfo.setPropId(speedUpInfo.getPropId());
                        useSpeedUpPropInfo.setNum(speedUpInfo.getNum());
                        useSpeedUpPropInfo.setTotalValue(speedUpInfo.getTotalValue());
                        recordInfo.addUseSpeedUpPropInfoList(useSpeedUpPropInfo);
                    }
                    list.add(recordInfo.build());
                }
            }
        }
        return list;
    }

    /**
     * 获取当前船只加速详情
     *
     * @param unionId
     * @return
     */
    public List<PeakSeacraftProto.PeakSeacraftSpeedUpInfo> getCurSpeedUpDetail(String unionId) {
        List<PeakSeacraftProto.PeakSeacraftSpeedUpInfo> list = new ArrayList<>();
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (unionInfo != null && unionInfo.getShipData() != null) {
            for (PeakSeacraftCurSpeedInfo item : unionInfo.getSpeedRecordList()) {
                PeakSeacraftProto.PeakSeacraftSpeedUpInfo.Builder speedInfo = PeakSeacraftProto.PeakSeacraftSpeedUpInfo.newBuilder();
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(item.getId());
                if (userBaseInfo != null) {
                    speedInfo.setUserName(userBaseInfo.getNickName());
                }
                speedInfo.setSpeed(item.getV());
                speedInfo.setEndTime(item.getEndT());
                list.add(speedInfo.build());
            }
        }
        return list;
    }


    /**
     * 同步 门客
     *
     * @param userPatronsInfoList
     */
    public void synUserInfo(List<PeakSeacraftProto.PeakSeacraftSynUserPatronsInfo> userPatronsInfoList) {
        long now = DateHelper.getCurrentTime();
        for (PeakSeacraftProto.PeakSeacraftSynUserPatronsInfo item : userPatronsInfoList) {
            long userId = item.getUserId();
            List<PeakSeacraftProto.PeakSeacraftPatronsEntity> patronsList = item.getPatronsListList();
            PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
            if (userInfo == null) {
                return;
            }
            // 遍历改变的门客 更改或替换  然后再遍历
            for (PeakSeacraftProto.PeakSeacraftPatronsEntity patronsEntity : patronsList) {
                PatronsInfo patronsInfoConfig = PatronsMgr.getPatronsInfoMap().get(patronsEntity.getPatronsId());
                PeakSeacraftTeamInfo teamInfo = userInfo.getBaseData().getShipMemberMap().get(patronsInfoConfig.getOccupation());
                if (null == teamInfo) {
                    teamInfo = new PeakSeacraftTeamInfo();
                    teamInfo.setType(patronsInfoConfig.getOccupation());
                    userInfo.getBaseData().getShipMemberMap().put(patronsInfoConfig.getOccupation(), teamInfo);
                }
                // 改变数值
                boolean change = false;
                // 替换门客
                boolean replace = false;
                for (PeakSeacraftPatronsInfo patronsInfo : teamInfo.getTeamList()) {
                    if (patronsInfo.getId() == patronsEntity.getPatronsId()) {
                        patronsInfo.setLv(patronsEntity.getLevel());
                        patronsInfo.setStageLv(patronsEntity.getStageLv());
                        patronsInfo.setSkinId(patronsEntity.getSkinId());
                        patronsInfo.setEarn(patronsEntity.getEarn());
                        patronsInfo.setPromotionId(patronsEntity.getPromotionId());
                        patronsInfo.setAddPlus(patronsEntity.getAddPlus());
                        change = true;
                        break;
                    }
                }
                if (!change && teamInfo.getTeamList().size() < PeakSeacraftActivityConfig.getTeamNum()) {
                    teamInfo.getTeamList().add(parseSouthSeaPatronsInfo(patronsEntity));
                    change = true;
                    replace = true;
                }
                if (!change) {
                    Iterator<PeakSeacraftPatronsInfo> iterator = teamInfo.getTeamList().iterator();
                    while (iterator.hasNext()) {
                        PeakSeacraftPatronsInfo patronsInfo = iterator.next();
                        // 比较战斗力
                        long value1 = patronsInfo.getEarn() * (1000 + patronsInfo.getAddPlus()) / 1000;
                        long value2 = patronsEntity.getEarn() * (1000 + patronsEntity.getAddPlus()) / 1000;
                        if (value1 < value2 || (value1 == value2 && patronsInfo.getId() < patronsEntity.getPatronsId())) {
                            // 移除最后一个 并 加入一个
                            teamInfo.getTeamList().remove(teamInfo.getTeamList().size() - 1);
                            //
                            teamInfo.getTeamList().add(parseSouthSeaPatronsInfo(patronsEntity));
                            change = true;
                            replace = true;
                            break;
                        }
                    }
                }
                if (change) {
                    List<PeakSeacraftPatronsInfo> tempList = new ArrayList<>(teamInfo.getTeamList());
                    tempList.sort((t1, t2) -> {
                        return PeakSeacraftActivityConfig.comparator(t1.getId(), t1.getEarn(), t1.getAddPlus(), t2.getId(), t2.getEarn(), t2.getAddPlus());
                    });
                    teamInfo.setTeamList(tempList);
                    if (replace) {
                        addLogPeakSeacraftTeam(userInfo, teamInfo, patronsInfoConfig.getOccupation(), now);
                    }
                }
            }
        }
    }


    public void addLogPeakSeacraftTeam(PeakSeacraftCrossUserInfo userInfo, PeakSeacraftTeamInfo teamInfo, int type, long now) {
        // 加变动日志
        List<Integer> patronsIdList = new ArrayList<>();
        long defendValue = 0;
        long addPlus = PeakSeacraftActivity.getTeamAddBuff(teamInfo);
        long attackValue = 0;
        for (PeakSeacraftPatronsInfo patronsInfo : teamInfo.getTeamList()) {
            patronsIdList.add(patronsInfo.getId());
            defendValue += patronsInfo.getEarn();
        }
        attackValue = defendValue * addPlus / 1000L;
        int area = 0;
        int group = 0;
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        if (null != unionInfo) {
            area = unionInfo.getUnionData().getArea();
            group = unionInfo.getUnionData().getGroupNum();
        }
        CrossAutoLogMgr.add(new LogPeakSeacraftTeam(activityId, userInfo.getBaseData().getUnionId(), type, userInfo.getBaseData().getUserId(),
                StringUtils.listToString(patronsIdList, ","), defendValue, attackValue, area, group));
    }

    public Map<String, PeakSeacraftUnionInfo> getUnionInfoMap() {
        return unionInfoMap;
    }

    /**
     * 获取玩家积分
     *
     * @param userId
     * @return
     */
    public int getUserScore(long userId) {
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo != null) {
            return userInfo.getBaseData().getScore();
        }
        return 0;
    }

    /**
     * 购买buff的值
     *
     * @param userInfo
     * @return
     */
    public int getBuyBuffValue(PeakSeacraftCrossUserInfo userInfo) {
        int totalValue = 0;
        if (userInfo.getChallengeData() != null) {
            for (Integer value : userInfo.getChallengeData().getBuffValueList()) {
                totalValue += value;
            }
        }
        return totalValue;
    }

    /**
     * 广播船只信息
     */
    public void broadcastShipInfoToInActivityUser(PeakSeacraftUnionInfo unionInfo, List<Long> excludeList) {
        PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.Builder broadcast = PeakSeacraftProto.BroadcastPeakSeacraftRespMsg.newBuilder();
        broadcast.setType(0);
        broadcast.setSeaShipInfo(unionInfo.builderPeakSeacraftShipInfo());
        PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.Builder toGameMsg = PeakSeacraftProto.PeakSeacraftBroadcastCrossToGameMsg.newBuilder();
        toGameMsg.setBroadcastMsg(broadcast);
        toGameMsg.setArea(unionInfo.getUnionData().getArea());
        toGameMsg.setGroup(unionInfo.getUnionData().getGroupNum());
        toGameMsg.setActivityId(activityId);
        toGameMsg.setUnionGroup(unionGroup);
        if (null != excludeList) {
            toGameMsg.addAllExcludeIds(excludeList);
        }

        config.getActivityInfo().getServerIdList().forEach(serverId -> {
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_BROADCAST_FROM_CROSS, toGameMsg));
        });
    }


    public PeakSeacraftProto.PeakSeacraftShipRecordInfo.Builder builderPeakSeacraftShipRecordInfo(PeakSeacraftCrossRecordData item) {
        PeakSeacraftProto.PeakSeacraftShipRecordInfo.Builder builder = PeakSeacraftProto.PeakSeacraftShipRecordInfo.newBuilder();
        builder.setMasterType(item.getMasterType());
        builder.setSonType(item.getSonType());
        builder.setUserId(item.getUserId());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(item.getUserId());
        if (userBaseInfo != null) {
            builder.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        }
        PeakSeacraftCrossUserInfo userInfo = userInfoMap.get(item.getUserId());
        if (userInfo != null) {
            PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(userInfo.getBaseData().getUnionId());
            if (unionInfo != null) {
                builder.setOwnUnionName(unionInfo.getUnionData().getUnionBaseInfo().getUnionName());
            }
        }
        if (!StringUtils.isNullOrEmpty(item.getTargetId())) {
            // 目标商会
            PeakSeacraftUnionInfo unionInfo = unionInfoMap.get(item.getTargetId());
            if (unionInfo != null) {
                builder.setUnionName(unionInfo.getUnionData().getUnionBaseInfo().getUnionName());
            }
        }
        builder.setMasterType(item.getMasterType());
        builder.setKillNum(item.getKillNum());
        builder.setScore(item.getScore());
        builder.setDurable(item.getDurable());
        builder.setGoodsUseNum(item.getGoodsUseNum());
        builder.setTime(item.getTime());
        builder.setPropId(item.getPropId());
        builder.setSpeed(item.getSpeed());
        builder.setContinueTime(item.getContinueTime());
        builder.setArea(item.getArea());
        builder.setGroup(item.getGroupNum());
        return builder;
    }

    private static PeakSeacraftPatronsInfo parseSouthSeaPatronsInfo(PeakSeacraftProto.PeakSeacraftPatronsEntity item) {
        PeakSeacraftPatronsInfo patronsInfo = new PeakSeacraftPatronsInfo();
        patronsInfo.setId(item.getPatronsId());
        patronsInfo.setLv(item.getLevel());
        patronsInfo.setStageLv(item.getStageLv());
        patronsInfo.setSkinId(item.getSkinId());
        patronsInfo.setEarn(item.getEarn());
        patronsInfo.setPromotionId(item.getPromotionId());
        patronsInfo.setAddPlus(item.getAddPlus());
        return patronsInfo;
    }

    public PeakSeacraftProto.PeakSeacraftChallengeInfo.Builder builderPeakSeacraftChallengeInfo(PeakSeacraftCrossUserInfo userInfo) {
        PeakSeacraftProto.PeakSeacraftChallengeInfo.Builder builder = PeakSeacraftProto.PeakSeacraftChallengeInfo.newBuilder();
        builder.setTargetUnionId(userInfo.getChallengeData().getTargetId());
        PeakSeacraftUnionInfo targetUnionInfo = unionInfoMap.get(userInfo.getChallengeData().getTargetId());
        if (targetUnionInfo != null) {
            UnionBaseInfo unionBaseInfo = targetUnionInfo.getUnionData().getUnionBaseInfo();
            builder.addAllUnionFlag(UnionHelper.getUnionFlag(unionBaseInfo));
            builder.setMemberNum(targetUnionInfo.getUnionData().getMemberMap().size());
            builder.setUnionHonerPoint(targetUnionInfo.getUnionData().getUnionBaseInfo().getHonors());
        }
        builder.setLockDurable(userInfo.getChallengeData().getLockDurable());
        builder.setDeductDurable(userInfo.getChallengeData().getDeductDurable());
        builder.setTeamType(userInfo.getChallengeData().getTeamType());
        // 小队门客赚钱 (出战后锁定)
        long lockEarn = 0;
        if (userInfo.getChallengeData().getTeamType() > 0) {
            for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
                lockEarn += item.getEarn();
            }
        }
        List<PeakSeacraftProto.PeakSeacraftPatronsInfo> list = builderPeakSeacraftPatronsInfoList(userInfo);
        if (list != null && list.size() > 0) {
            builder.addAllPatronsInfoList(list);
        }
        builder.setWinStreakNum(userInfo.getChallengeData().getWinStreakNum());
        builder.setCanRecWinStreakReward(canRecWinStreakReward(userInfo));
        builder.setBuffId(userInfo.getChallengeData().getBuyBuffId());
        builder.setAttackedNum(userInfo.getChallengeData().getAttackedList().size());
        builder.setBuffValue(getBuyBuffValue(userInfo));
        builder.setLockEarn(lockEarn);
        builder.setAttackedUnionNum(userInfo.getBaseData().getAttackNum());
        builder.setTargetUnionRank(userInfo.getChallengeData().getTargetUnionRank());
        builder.setTargetUnionGroupRank(userInfo.getChallengeData().getTargetUnionGroupRank());
        for (Map.Entry<Long, PeakSeacraftTeamInfo> entry : userInfo.getChallengeData().getRandomMap().entrySet()) {
            PeakSeacraftProto.PeakSeacraftTargetInfo.Builder targetInfo = PeakSeacraftProto.PeakSeacraftTargetInfo.newBuilder();
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(entry.getKey());
            PlayerProto.PlayerDataTempMsg.Builder player = PlayerProto.PlayerDataTempMsg.newBuilder();
            if (userBaseInfo != null) {
                player.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            }
            player.setUserId(entry.getKey());
            targetInfo.setTargetInfo(player);
            targetInfo.setTeamType(entry.getValue().getType());
            builder.addTargetInfoList(targetInfo);
        }
        builder.setChallengeType(userInfo.getChallengeData().getAttackType());

        PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        if (null != unionInfo) {
            builder.setArea(unionInfo.getUnionData().getArea());
            builder.setGroup(unionInfo.getUnionData().getGroupNum());
        }

        return builder;
    }

    /**
     * 获取玩家挑战数据的门客
     *
     * @param userInfo
     * @return
     */
    public static List<PeakSeacraftProto.PeakSeacraftPatronsInfo> builderPeakSeacraftPatronsInfoList(PeakSeacraftCrossUserInfo userInfo) {
        List<PeakSeacraftProto.PeakSeacraftPatronsInfo> list = new ArrayList<>();
        if (userInfo != null && userInfo.getChallengeData() != null) {
            for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
                list.add(PeakSeacraftProto.PeakSeacraftPatronsInfo.newBuilder().setBlood(item.getBlood()).setMaxBlood(item.getMaxBlood()).setAddPlus(item.getAddPlus()).setPatronsId(item.getId()).build());
            }
        }
        return list;
    }

    public PeakSeacraftProto.PeakSeacraftBattleRecordInfo.Builder builderPeakSeacraftBattleRecordInfo(PeakSeacraftBattleDetailData item) {
        PeakSeacraftProto.PeakSeacraftBattleRecordInfo.Builder builder = PeakSeacraftProto.PeakSeacraftBattleRecordInfo.newBuilder();
        builder.setType(item.getMasterType());
        builder.setUnionUid(item.getTargetUnionId());
        PeakSeacraftUnionInfo targetUnionInfo = unionInfoMap.get(item.getTargetUnionId());
        if (targetUnionInfo != null && targetUnionInfo.getUnionData().getUnionBaseInfo() != null) {
            builder.setUnionInfo(UnionBasePb.parseUnionBaseTempMsg(targetUnionInfo.getUnionData().getUnionBaseInfo()));
        }
        builder.setSuddenAttack(calTotalDamage(item.getRaidAttackMap()));
        builder.setAttack(calTotalDamage(item.getAttackMap()));
        builder.setFire(calTotalDamage(item.getUseGoodMap()));
        builder.setTime(item.getTime());
        builder.setArea(item.getArea());
        builder.setGroup(item.getGroupNum());
        return builder;
    }

    /**
     * 计算总伤害
     *
     * @param detailData
     * @return
     */
    private long calTotalDamage(PeakSeacraftBattleDetailData detailData) {
        long totalValue = 0;
        totalValue += calTotalDamage(detailData.getAttackMap());
        totalValue += calTotalDamage(detailData.getRaidAttackMap());
        totalValue += calTotalDamage(detailData.getUseGoodMap());
        detailData.setTotalDamage(totalValue);
        return totalValue;
    }

    private long calTotalDamage(Map<Long, PeakSeacraftBattleDetailInfo> detailInfoMap) {
        long totalValue = 0;
        for (PeakSeacraftBattleDetailInfo item : detailInfoMap.values()) {
            totalValue += item.getV();
        }
        return totalValue;
    }


    public List<PeakSeacraftProto.PeakSeacraftMemberBattleDetailInfo> builderPeakSeacraftMemberBattleDetailInfoList(Map<Long, PeakSeacraftBattleDetailInfo> map) {
        List<PeakSeacraftProto.PeakSeacraftMemberBattleDetailInfo> list = new ArrayList<>();
        for (Map.Entry<Long, PeakSeacraftBattleDetailInfo> entry : map.entrySet()) {
            if (entry.getValue().getV() <= 0) {
                continue;
            }
            PeakSeacraftProto.PeakSeacraftMemberBattleDetailInfo.Builder builder = PeakSeacraftProto.PeakSeacraftMemberBattleDetailInfo.newBuilder();
            builder.setUserName(CrossUserMgr.getUserName(entry.getKey()));
            builder.setServerId(CrossUserMgr.getServerIdByUserId(entry.getKey()));
            builder.setValue(entry.getValue().getV());
            builder.setTime(entry.getValue().getT());
            list.add(builder.build());
        }
        return list;
    }


    /**
     * 获取小队的天赋加成
     *
     * @param teamInfo
     * @return
     */
    public static long getTeamAddBuff(PeakSeacraftTeamInfo teamInfo) {
        int addPlus = 0;
        for (PeakSeacraftPatronsInfo item : teamInfo.getTeamList()) {
            addPlus += item.getAddPlus();
        }
        return addPlus;
    }

    public int getActivityId() {
        return activityId;
    }

    public PeakSeacraftProto.PeakSeacraftSynPromotionUnionCrossToGameMsg.Builder getPromotionUnion() {
        PeakSeacraftProto.PeakSeacraftSynPromotionUnionCrossToGameMsg.Builder builder = PeakSeacraftProto.PeakSeacraftSynPromotionUnionCrossToGameMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.addAllUnionId(unionInfoMap.keySet());
        return builder;
    }

    public Map<Long, PeakSeacraftCrossUserInfo> getUserInfoMap() {
        return userInfoMap;
    }

    public List<String> getAllUnionIdList() {
        return new ArrayList<>(unionInfoMap.keySet());
    }


    /**
     * 获取当前调整的小队血量
     *
     * @param userInfo
     * @return
     */
    public long getTeamBlood(PeakSeacraftCrossUserInfo userInfo) {
        long teamBlood = 0;
        if (userInfo.getChallengeData() != null) {
            for (PeakSeacraftLockPatronsInfo item : userInfo.getChallengeData().getPatronsInfoList()) {
                if (item.getBlood() > 0) {
                    teamBlood += item.getBlood();
                }
            }
        }
        return teamBlood;
    }

    /**
     * 加进攻细节
     *
     * @param attackUnion 攻击联盟
     * @param attackId    攻击玩家id
     * @param defendUnion 防守联盟
     * @param sonType
     * @param durable
     * @param time
     */
    public void addBattleDetail(PeakSeacraftUnionInfo attackUnion, long attackId, PeakSeacraftUnionInfo defendUnion, int sonType, int durable, long time) {
        attackUnion.addBattleDetail(0, sonType, defendUnion.getUnionData().getUnionId(), attackId, durable, time, attackUnion.getUnionData().getArea(), attackUnion.getUnionData().getGroupNum());
        defendUnion.addBattleDetail(1, sonType, attackUnion.getUnionData().getUnionId(), attackId, durable, time, attackUnion.getUnionData().getArea(), attackUnion.getUnionData().getGroupNum());
    }


    /**
     * 获取本轮的距离
     *
     * @return
     */
    protected long getRoundDistance() {
        long distance = Long.MAX_VALUE;
        int round = getActivityCurRound();
        PeakSeacraftActivityConfig activityConfig = config;
        if (round > activityConfig.getMaxRoundCount()) {
            round = activityConfig.getMaxRoundCount();
        }
        if (activityConfig != null && activityConfig.getMaxRoundCount() >= round) {
            Integer[] openTime = activityConfig.roundTimeList.get(round - 1);
            if (openTime != null) {
                distance = activityConfig.getSEACRAFT_CRAFT_DISTANCE() * ((openTime[1] - openTime[0]) / DateHelper.HOUR_SECONDS);
            }
        }
        return distance;
    }

    protected int getUnionRank(PeakSeacraftUnionInfo unionInfo, boolean refreshUnionRank) {
        if (refreshUnionRank) {
            refreshUnionRank();
        }
        return unionInfo.getUnionData().getRank();
    }

    public PeakSeacraftGroupInfo getGroupInfo(int area, int group, boolean isNewIfNull) {
        PeakSeacraftGroupInfo groupInfo = null;
        if (areaGroupMap.containsKey(area)) {
            groupInfo = areaGroupMap.get(area).get(group);
        }

        if (null == groupInfo && isNewIfNull) {
            synchronized (areaGroupMap) {
                if (areaGroupMap.containsKey(area)) {
                    groupInfo = areaGroupMap.get(area).get(group);
                } else {
                    areaGroupMap.put(area, new ConcurrentHashMap<>());
                }
                if (null == groupInfo) {
                    groupInfo = new PeakSeacraftGroupInfo(area, group, getActivityCurRound(), activityId);
                    areaGroupMap.get(area).put(group, groupInfo);
                }
            }
        }
        return groupInfo;
    }

    /**
     * 总商会排序规则
     *
     * @param t1
     * @param t2
     * @return
     */
    private int unionRankCompare(PeakSeacraftUnionInfo t1, PeakSeacraftUnionInfo t2) {
        if (t1.getUnionData().getArea() != t2.getUnionData().getArea()) {
            // 晋级到的轮次不同
            return Integer.compare(t2.getUnionData().getArea(), t1.getUnionData().getArea());
        } else {
            int compare = Integer.compare(t2.nowScore, t1.nowScore);
            if (compare == 0) {
                int curRound = getCurRound();
                if (config.isPrepareTime() && curRound > 1) {//第二轮开始的备战期，到达数据重置了，要取上一轮的。
                    int lastRound = curRound - 1;
                    long arriveTime1 = 0;
                    long arriveTime2 = 0;
                    long distance1 = 0;
                    long distance2 = 0;
                    PeakSeacraftResultInfo resultInfo1 = t1.getUnionData().getResultMap().get(lastRound);
                    if (null != resultInfo1) {
                        arriveTime1 = resultInfo1.getArriveTime();
                        distance1 = resultInfo1.getDistance();
                    }
                    PeakSeacraftResultInfo resultInfo2 = t2.getUnionData().getResultMap().get(lastRound);
                    if (null != resultInfo2) {
                        arriveTime2 = resultInfo2.getArriveTime();
                        distance2 = resultInfo2.getDistance();
                    }
                    if (distance1 != distance2) {
                        return Long.compare(distance2, distance1);
                    } else if (arriveTime1 != arriveTime2){
                        return Long.compare(arriveTime1, arriveTime2);
                    }

                } else {
                    if (t1.distance != t2.distance) {
                        // 行驶的距离不同
                        return Long.compare(t2.distance, t1.distance);
                    } else {
                        long roundDistance = getRoundDistance();
                        if (t1.distance == roundDistance && t1.getShipData().getEndTime() != t2.getShipData().getEndTime()) {
                            // 到达了终点 到达时间不同
                            return Long.compare(t1.getShipData().getEndTime(), t2.getShipData().getEndTime());
                        }
                    }
                }
                if (0 == compare) {
                    compare = t2.getUnionData().getTotalAbility().compareTo(t1.getUnionData().getTotalAbility());
                }
            }
            return compare;
        }
    }

    public List<PeakSeacraftCrossUserGuessData> getGuessList() {
        List<PeakSeacraftCrossUserGuessData> list = new ArrayList<>();
        synchronized (userGuessDataMap) {
            list.addAll(userGuessDataMap.values());
        }
        return list;
    }

    /**
     * 更新全部组内排名
     */
    private void sortUnionGroupRank() {
        synchronized (areaGroupMap) {
            for (Map<Integer, PeakSeacraftGroupInfo> groupInfoMap : areaGroupMap.values()) {
                for (PeakSeacraftGroupInfo groupInfo : groupInfoMap.values()) {
                    groupInfo.sortUnionList(this);
                }
            }
        }
    }

    private UnionActivityRankProto.UnionActivityRankListMsg getUnionRankListMsg() {
        synchronized (rankListMsg) {
            return rankListMsg.build();
        }
    }

    public void parseUnionRankMsgByUserId(long userId, StrongholdWarProto.StrongholdActivityUnionRankListRespMsg.Builder msg) {
        UnionActivityRankProto.UnionActivityRankListMsg rankMsg = getUnionRankListMsg();
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        String ownUnionId = "";
        if (null != userInfo) {
            ownUnionId = userInfo.getBaseData().getUnionId();
        }
        msg.setMyRank(-1);
        msg.setValue(BigInteger.ZERO.toString());
        msg.setRankList(rankMsg);
        int rank = 0;
        for (UnionActivityRankProto.UnionActivityRankTempMsg unionActivityRankTempMsg : rankMsg.getRankListList()) {
            rank++;
            if (unionActivityRankTempMsg.getUnionUid().equals(ownUnionId)) {
                msg.setMyRank(rank);
                msg.setValue(unionActivityRankTempMsg.getValue());
                break;
            }
        }
    }

    public void sortAndParseUnionRankMsg() {
        if (getCurRound() > config.getMaxRoundCount()) {
            return;
        }
        sortUnionGroupRank();
        parseUnionRankMsg(unionRankSort());
    }

    private void parseUnionRankMsg(List<PeakSeacraftUnionInfo> list) {
        UnionActivityRankProto.UnionActivityRankListMsg.Builder builder = UnionActivityRankProto.UnionActivityRankListMsg.newBuilder();
        for (PeakSeacraftUnionInfo unionInfo : list) {
            UnionActivityRankProto.UnionActivityRankTempMsg.Builder tempMsg = UnionActivityRankProto.UnionActivityRankTempMsg.newBuilder();
            tempMsg.setUnionUid(unionInfo.getUnionData().getUnionId());
            tempMsg.setUnionBaseData(UnionBasePb.parseUnionBaseTempMsg(unionInfo.getUnionData().getUnionBaseInfo()));
            int score = unionInfo.nowScore;
            tempMsg.setValue(String.valueOf(score));
//            tempMsg.setParamValue(unionInfo.getUnionRankParamValue(this));
            builder.addRankList(tempMsg);
        }
        synchronized (rankListMsg) {
            rankListMsg = builder;
        }
    }

    private void notifyUpdateUserCondition(long serverId, long userId, int area) {
        //更新到达海域成就
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_UPDATE_USER_CONDITION_FROM_CROSS,
                PeakSeacraftProto.PeakSeacraftUpdateUserConditionMsg.newBuilder().setActivityId(activityId).setArea(area)));
    }

    public PeakSeacraftProto.PeakSeacraftGetUnionRoundResultRespMsg.Builder getUnionRoundResult(String unionId) {
        PeakSeacraftProto.PeakSeacraftGetUnionRoundResultRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetUnionRoundResultRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUnionId(unionId);
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(unionId, false);
        if (null == unionInfo) {
            return builder.setRet(GameErrorCode.E_SEACRAFT_SOUTH_SEA_ACTIVITY_NO_PROMOTION);
        }
        builder.addAllRoundResult(getUnionResultList(unionInfo));
        if (config.isOpenTime() && !unionInfo.getUnionData().getResultMap().containsKey(getCurRound())) {
            PeakSeacraftProto.PeakSeacraftResult.Builder curRoundResult = PeakSeacraftProto.PeakSeacraftResult.newBuilder();
            curRoundResult.setRound(getCurRound());
            curRoundResult.setGroupRank(unionInfo.getUnionData().getGroupRank());
            curRoundResult.setGroup(unionInfo.getUnionData().getGroupNum());
            curRoundResult.setArea(unionInfo.getUnionData().getArea());
            if (null != unionInfo.getShipData()) {
                curRoundResult.setDistance(unionInfo.getShipData().getDistance());
                curRoundResult.setArriveTime(unionInfo.getShipData().getEndTime());
            }
            curRoundResult.setRank(unionInfo.getUnionData().getRank());
            builder.addRoundResult(curRoundResult);
        }
        for (PeakSeacraftCrossUserInfo crossUserInfo : unionInfo.getMemberMap().values()) {
            PeakSeacraftProto.PeakSeacraftMemberScoreTemp.Builder scoreMsg = PeakSeacraftProto.PeakSeacraftMemberScoreTemp.newBuilder();
            scoreMsg.setScore(crossUserInfo.getBaseData().getScore());
            scoreMsg.setUserId(crossUserInfo.getBaseData().getUserId());
            scoreMsg.setUserName(CrossUserMgr.getUserName(crossUserInfo.getBaseData().getUserId()));
            builder.addMemberScore(scoreMsg);
        }

        return builder;
    }

    public PeakSeacraftProto.PeakSeacraftGetMemberRoundScoreRespMsg.Builder getMemberRoundScore(long userId) {
        PeakSeacraftProto.PeakSeacraftGetMemberRoundScoreRespMsg.Builder builder = PeakSeacraftProto.PeakSeacraftGetMemberRoundScoreRespMsg.newBuilder();
        builder.setRet(0);
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        int curRound = getCurRound();
        if (null != userInfo) {
            PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
            if (null != unionInfo) {
                for (int i = 1; i <= curRound && i <= config.getMaxRoundCount(); i++) {
                    PeakSeacraftProto.PeakSeacraftMemberRoundScoreTemp.Builder scoreMsg = PeakSeacraftProto.PeakSeacraftMemberRoundScoreTemp.newBuilder();
                    scoreMsg.setRound(i);
                    scoreMsg.setScore(0);
                    scoreMsg.setArea(1);
                    if (userInfo.getBaseData().getRoundScore().containsKey(i)) {
                        int score = userInfo.getBaseData().getRoundScore().get(i);
                        scoreMsg.setScore(score);
                    } else if (i == curRound && config.isPrepareTime()){
                        //备战期不显示本轮伤害积分
                        continue;
                    }
                    if (i == unionInfo.getUnionData().getRound()) {
                        scoreMsg.setArea(unionInfo.getUnionData().getArea());
                    } else {
                        PeakSeacraftResultInfo resultInfo = unionInfo.getUnionData().getResultMap().get(i);
                        if (resultInfo != null) {
                            scoreMsg.setArea(resultInfo.getArea());
                        }
                    }
                    builder.addRoundScore(scoreMsg);
                }
            }
        }
        return builder;
    }

    private void updateShipNumber() {
        synchronized (areaGroupMap) {
            for (Map<Integer, PeakSeacraftGroupInfo> groupInfoMap : areaGroupMap.values()) {
                for (PeakSeacraftGroupInfo groupInfo : groupInfoMap.values()) {
                    groupInfo.updateShipNumber();
                }
            }
        }
    }

    public void addGroupChatMsg(int area, int group, WorldMessageProto.WorldMessageTempMsg chatMsg) {
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(area, group, false);
        if (groupInfo == null) {
            return;
        }
        groupInfo.addChatMsg(chatMsg);

        for (Long serverId : getConfig().getActivityInfo().getServerIdList()) {
            MessageHelper.sendPacket(serverId, 0,
                    YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_SEACRAFT_CHAT_BROADCAST_FROM_CROSS,
                            chatMsg));
        }
    }

    public WorldMessageProto.WorldMessageListMsg.Builder getAreaGroupChatListMsg(int area, int group) {
        PeakSeacraftGroupInfo groupInfo = getGroupInfo(area, group, false);
        if (groupInfo == null) {
            return WorldMessageProto.WorldMessageListMsg.newBuilder();
        }
        return groupInfo.getChatListMsg();
    }

    public void clearChatMsg() {
        for (Map<Integer, PeakSeacraftGroupInfo> groupInfoMap : areaGroupMap.values()) {
            for (PeakSeacraftGroupInfo groupInfo : groupInfoMap.values()) {
                groupInfo.clearChatMsg();
            }
        }
    }

    public String getUserAreaParam(long userId) {
        PeakSeacraftCrossUserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            return null;
        }
        PeakSeacraftUnionInfo unionInfo = getUnionInfo(userInfo.getBaseData().getUnionId(), false);
        if (unionInfo == null) {
            return null;
        }

        JSONObject json = new JSONObject();
        json.put("area", unionInfo.getUnionData().getArea());
        json.put("group", unionInfo.getUnionData().getGroupNum());
        return json.toJSONString();
    }

}
